Fri Nov 12 12:07:50 2010

Asterisk developer's documentation


res_config_ldap.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static char base_distinguished_name [512]
static struct ldap_table_configbase_table_config
static time_t connect_time
static struct ast_cli_entry ldap_cli []
static struct ast_config_engine ldap_engine
static ast_mutex_t ldap_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static LDAP * ldapConn
static char pass [50]
static struct ldap_table_configstatic_table_config
static char url [512]
static char user [512]
static int version = 3

Detailed Description

ldap plugin for portable configuration engine (ARA)

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

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

static void __unreg_module ( void   )  [static]

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

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

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

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

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

caller should free returned pointer

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

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

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

00987 {
00988    const struct category_and_metric *as = a;
00989    const struct category_and_metric *bs = b;
00990 
00991    if (as->metric < bs->metric)
00992       return -1;
00993    else if (as->metric > bs->metric)
00994       return 1;
00995    else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0)
00996       return strcmp(as->name, bs->name);
00997 
00998    /* if the metric and the category name is the same, we check the variable metric */
00999    if (as->var_metric < bs->var_metric)
01000       return -1;
01001    else if (as->var_metric > bs->var_metric)
01002       return 1;
01003 
01004    return 0;
01005 }

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

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

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

static const char* convert_attribute_name_from_ldap ( struct ldap_table_config table_config,
const char *  attribute_name 
) [static]

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

Definition at line 240 of file res_config_ldap.c.

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

Referenced by realtime_ldap_entry_to_var(), and realtime_ldap_result_to_vars().

00242 {
00243    int i = 0;
00244    struct ldap_table_config *configs[] = { table_config, base_table_config };
00245 
00246    for (i = 0; i < ARRAY_LEN(configs); i++) {
00247       struct ast_variable *attribute;
00248 
00249       if (!configs[i])
00250          continue;
00251 
00252       attribute = configs[i]->attributes;
00253       for (; attribute; attribute = attribute->next) {
00254          if (strcasecmp(attribute_name, attribute->value) == 0)
00255             return attribute->name;
00256       }
00257    }
00258 
00259    return attribute_name;
00260 }

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

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

Definition at line 217 of file res_config_ldap.c.

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

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

00219 {
00220    int i = 0;
00221    struct ldap_table_config *configs[] = { table_config, base_table_config };
00222 
00223    for (i = 0; i < ARRAY_LEN(configs); i++) {
00224       struct ast_variable *attribute;
00225 
00226       if (!configs[i])
00227          continue;
00228 
00229       attribute = configs[i]->attributes;
00230       for (; attribute; attribute = attribute->next) {
00231          if (!strcasecmp(attribute_name, attribute->name))
00232             return attribute->value;
00233       }
00234    }
00235 
00236    return attribute_name;
00237 }

static int is_ldap_connect_error ( int  err  )  [static]

Definition at line 534 of file res_config_ldap.c.

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

00535 {
00536    return (err == LDAP_SERVER_DOWN
00537          || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00538 }

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

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

Referenced by realtime_ldap_base_ap().

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

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

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

01670 {
01671    int bind_result = 0;
01672    struct berval cred;
01673 
01674    if (ldapConn) {
01675       ast_debug(2, "Everything seems fine.\n");
01676       return 1;
01677    }
01678 
01679    if (ast_strlen_zero(url)) {
01680       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap database\n");
01681       return 0;
01682    }
01683 
01684    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01685       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01686       return 0;
01687    }
01688 
01689    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01690       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01691    }
01692 
01693    if (!ast_strlen_zero(user)) {
01694       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01695       cred.bv_val = (char *) pass;
01696       cred.bv_len = strlen(pass);
01697       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01698    } else {
01699       ast_debug(2, "bind %s anonymously\n", url);
01700       cred.bv_val = NULL;
01701       cred.bv_len = 0;
01702       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01703    }
01704    if (bind_result == LDAP_SUCCESS) {
01705       ast_debug(2, "Successfully connected to database.\n");
01706       connect_time = time(NULL);
01707       return 1;
01708    } else {
01709       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01710       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01711       ldapConn = NULL;
01712       return 0;
01713    }
01714 }

static void ldap_table_config_add_attribute ( struct ldap_table_config table_config,
const char *  attribute_name,
const char *  attribute_value 
) [static]

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

Definition at line 180 of file res_config_ldap.c.

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

Referenced by parse_config().

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

static int load_module ( void   )  [static]

Definition at line 1507 of file res_config_ldap.c.

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

01508 {
01509    if (parse_config() < 0) {
01510       ast_log(LOG_NOTICE, "Cannot load LDAP RealTime driver.\n");
01511       return 0;
01512    }
01513 
01514    ast_mutex_lock(&ldap_lock);
01515 
01516    if (!ldap_reconnect()) 
01517       ast_log(LOG_WARNING, "Couldn't establish connection. Check debug.\n");
01518 
01519    ast_config_engine_register(&ldap_engine);
01520    ast_verb(1, "LDAP RealTime driver loaded.\n");
01521    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01522 
01523    ast_mutex_unlock(&ldap_lock);
01524 
01525    return 0;
01526 }

int parse_config ( void   )  [static]

< using the [config] context for Static RealTime

Definition at line 1576 of file res_config_ldap.c.

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

Referenced by load_module(), and reload().

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

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

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

00908 {
00909    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00910    struct ast_variable *var = NULL;
00911 
00912    if (vars) {
00913       struct ast_variable *last_var = NULL;
00914       struct ast_variable **p = vars;
00915       while (*p) {
00916          if (last_var) {
00917             while (last_var->next)
00918                last_var = last_var->next;
00919             last_var->next = *p;
00920          } else {
00921             var = *p;
00922             last_var = var;
00923          }
00924          p++;
00925       }
00926       free(vars);
00927    }
00928    return var;
00929 }

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

References realtime_ldap_base_ap().

Referenced by config_ldap().

00891 {
00892    struct ast_variable **vars = NULL;
00893    va_list ap;
00894 
00895    va_start(ap, table_name);
00896    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
00897    va_end(ap);
00898 
00899    return vars;
00900 }

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

LDAP base function.

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

Definition at line 717 of file res_config_ldap.c.

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

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

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

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

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

Returns:
a linked list of ast_variable variables.

Definition at line 265 of file res_config_ldap.c.

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

Referenced by realtime_ldap_result_to_vars().

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

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

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

Referenced by ldap_loadentry(), and realtime_ldap_base_ap().

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

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

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

01717 {
01718    char status[256], credentials[100] = "";
01719    int ctimesec = time(NULL) - connect_time;
01720 
01721    switch (cmd) {
01722    case CLI_INIT:
01723       e->command = "realtime show ldap status";
01724       e->usage =
01725          "Usage: realtime show ldap status\n"
01726          "               Shows connection information for the LDAP RealTime driver\n";
01727       return NULL;
01728    case CLI_GENERATE:
01729       return NULL;
01730    }
01731 
01732    if (!ldapConn)
01733       return CLI_FAILURE;
01734 
01735    if (!ast_strlen_zero(url)) 
01736       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01737 
01738    if (!ast_strlen_zero(user))
01739       snprintf(credentials, sizeof(credentials), " with username %s", user);
01740 
01741    if (ctimesec > 31536000) {
01742       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01743             status, credentials, ctimesec / 31536000,
01744             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01745             (ctimesec % 3600) / 60, ctimesec % 60);
01746    } else if (ctimesec > 86400) {
01747       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01748             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01749             (ctimesec % 3600) / 60, ctimesec % 60);
01750    } else if (ctimesec > 3600) {
01751       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01752             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01753             ctimesec % 60);
01754    } else if (ctimesec > 60) {
01755       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01756                ctimesec / 60, ctimesec % 60);
01757    } else {
01758       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01759    }
01760 
01761    return CLI_SUCCESS;
01762 }

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

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

00940 {
00941    struct ast_variable **vars =
00942       realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00943    struct ast_config *cfg = NULL;
00944 
00945    if (vars) {
00946       cfg = ast_config_new();
00947       if (!cfg) {
00948          ast_log(LOG_ERROR, "Unable to create a config!\n");
00949       } else {
00950          struct ast_variable **p = vars;
00951 
00952          while (*p) {
00953             struct ast_category *cat = NULL;
00954             cat = ast_category_new("", table_name, -1);
00955             if (!cat) {
00956                ast_log(LOG_ERROR, "Unable to create a new category!\n");
00957                break;
00958             } else {
00959                struct ast_variable *var = *p;
00960                while (var) {
00961                   struct ast_variable *next = var->next;
00962                   var->next = NULL;
00963                   ast_variable_append(cat, var);
00964                   var = next;
00965                }
00966             }
00967             ast_category_append(cfg, cat);
00968             p++;
00969          }
00970       }
00971       free(vars);
00972    }
00973    return cfg;
00974 
00975 }

static int reload ( void   )  [static]

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

01550 {
01551    /* Aquire control before doing anything to the module itself. */
01552    ast_mutex_lock(&ldap_lock);
01553 
01554    if (ldapConn) {
01555       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01556       ldapConn = NULL;
01557    }
01558 
01559    if (parse_config() < 0) {
01560       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01561       ast_mutex_unlock(&ldap_lock);
01562       return 0;
01563    }     
01564 
01565    if (!ldap_reconnect()) 
01566       ast_log(LOG_WARNING, "Couldn't establish connection. Check debug.\n");
01567 
01568    ast_verb(2, "LDAP RealTime reloaded.\n");
01569 
01570    /* Done reloading. Release lock so others can now use driver. */
01571    ast_mutex_unlock(&ldap_lock);
01572 
01573    return 0;
01574 }

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

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

Definition at line 662 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

00663 {
00664    int search_len = strlen(search);
00665    int by_len = strlen(by);
00666    int replaced = 0;
00667    char *p = strstr(string, search);
00668    if (p) {
00669       replaced = 1;
00670       while (p) {
00671          if (by_len == search_len)
00672             memcpy(p, by, by_len);
00673          else {
00674             memmove(p + by_len, p + search_len,
00675                   strlen(p + search_len) + 1);
00676             memcpy(p, by, by_len);
00677          }
00678          p = strstr(p + by_len, search);
00679       }
00680    }
00681    return replaced;
00682 }

static int semicolon_count_str ( const char *  somestr  )  [static]

for the semicolon delimiter

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

Definition at line 152 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

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

static int semicolon_count_var ( struct ast_variable var  )  [static]

Definition at line 167 of file res_config_ldap.c.

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

Referenced by realtime_ldap_result_to_vars().

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

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

caller should free returned pointer

Definition at line 620 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

00621 {
00622 #define MAXRESULT 2048
00623    char *ret_string = NULL;
00624 
00625    if (!ast_strlen_zero(string)) {
00626       ret_string = ast_calloc(1, MAXRESULT);
00627       pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
00628    }
00629    ast_debug(2, "substituted: string: '%s' => '%s' \n",
00630       string, ret_string);
00631    return ret_string;
00632 }

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

Find a table_config - Should be locked before using it.

Note:
This function assumes ldap_lock to be locked.

Definition at line 124 of file res_config_ldap.c.

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

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

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

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

Create a new table_config.

Definition at line 105 of file res_config_ldap.c.

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

Referenced by parse_config().

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

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

Definition at line 198 of file res_config_ldap.c.

References ldap_table_config::additional_filter, 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().

00199 {
00200    struct ldap_table_config *c;
00201 
00202    while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
00203       if (c->table_name)
00204          free(c->table_name);
00205       if (c->additional_filter)
00206          free(c->additional_filter);
00207       if (c->attributes)
00208          ast_variables_destroy(c->attributes);
00209       free(c);
00210    }
00211 
00212    base_table_config = NULL;
00213    static_table_config = NULL;
00214 }

static int unload_module ( void   )  [static]

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

01529 {
01530    /* Aquire control before doing anything to the module itself. */
01531    ast_mutex_lock(&ldap_lock);
01532 
01533    table_configs_free();
01534 
01535    if (ldapConn) {
01536       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01537       ldapConn = NULL;
01538    }
01539    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01540    ast_config_engine_deregister(&ldap_engine);
01541    ast_verb(1, "LDAP RealTime unloaded.\n");
01542 
01543    /* Unlock so something else can destroy the lock. */
01544    ast_mutex_unlock(&ldap_lock);
01545 
01546    return 0;
01547 }

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

Definition at line 1314 of file res_config_ldap.c.

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

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

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

Definition at line 1127 of file res_config_ldap.c.

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

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

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

Find variable by name.

Definition at line 137 of file res_config_ldap.c.

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

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

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1768 of file res_config_ldap.c.

Definition at line 1768 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 69 of file res_config_ldap.c.

time_t connect_time [static]

Definition at line 71 of file res_config_ldap.c.

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

Definition at line 100 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

Definition at line 1498 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]
LDAP* ldapConn [static]

Definition at line 65 of file res_config_ldap.c.

char pass[50] [static]
char url[512] [static]
char user[512] [static]

Definition at line 67 of file res_config_ldap.c.

int version = 3 [static]

Generated by  doxygen 1.6.2