Mon Jun 27 16:51:19 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static LDAP * ldapConn
static char pass [512]
static struct ldap_table_configstatic_table_config
static char url [512]
static char user [512]
static int version


Detailed Description

ldap plugin for portable configuration engine (ARA)

Author:
Mark Spencer <markster@digium.com>

Manuel Guesdon

Carl-Einar Thorner <cthorner@voicerd.com>

Russell Bryant <russell@digium.com>

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

Definition in file res_config_ldap.c.


Define Documentation

#define MAXRESULT   2048

#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"

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

static void __unreg_module ( void   )  [static]

Definition at line 1809 of file res_config_ldap.c.

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

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

Definition at line 693 of file res_config_ldap.c.

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

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

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

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

Note:
caller should free returned pointer

Definition at line 642 of file res_config_ldap.c.

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

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

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

static int compare_categories ( const void *  a,
const void *  b 
) [static]

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

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

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

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

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

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

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

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

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

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

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

< not using this

Definition at line 553 of file res_config_ldap.c.

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

Referenced by realtime_ldap_base_ap().

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

static int ldap_reconnect ( void   )  [static]

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

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

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

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

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

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

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

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

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

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

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

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

same as realtime_ldap_base_ap but take variable arguments count list

Definition at line 903 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

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

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

LDAP base function.

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

Definition at line 726 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_variables_destroy(), base_table_config, cleaned_basedn(), filter(), is_ldap_connect_error(), ldap_loadentry(), ldap_lock, ldap_reconnect(), 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().

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

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

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_memfree(ldap_attribute_name);
00347       ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00348    }
00349    ber_free(ber, 0);
00350 
00351    return var;
00352 }

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

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

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

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

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

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

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

static int reload ( void   )  [static]

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

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

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

Replace <search> by <by> in string.

Note:
No check is done on string allocated size !

Definition at line 670 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

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

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

for the semicolon delimiter

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

Definition at line 152 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

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

static int semicolon_count_var ( struct ast_variable var  )  [static]

Definition at line 167 of file res_config_ldap.c.

References ast_debug, semicolon_count_str(), ast_variable::value, 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 628 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

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

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

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

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

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

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

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

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

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

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

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

struct ast_module_info* ast_module_info = &__mod_info [static]

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

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 Mon Jun 27 16:51:19 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7