Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Enumerations | Functions | Variables
back-meta.h File Reference
#include "proto-meta.h"
#include "rewrite.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  ldapmap
struct  ldapmapping
struct  ldaprwmap
struct  dncookie
struct  metasingleconn_t
struct  metaconn_t
struct  metasubtree_t
struct  metatarget_t
struct  metadncache_t
struct  metacandidates_t
struct  metainfo_t
union  metasubtree_t.ms_un
struct  metasubtree_t.ms_un.msu_regex
struct  metainfo_t.mi_conn_priv

Defines

#define META_BACK_PRINT_CONNTREE   0
#define BACKLDAP_MAP   0
#define BACKLDAP_REMAP   1
#define META_BACK_FCONN_INITED   (0x00100000U)
#define META_BACK_FCONN_CREATING   (0x00200000U)
#define META_BACK_CONN_INITED(lc)   LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_SET(lc)   LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_CLEAR(lc)   LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_CPY(lc, mlc)   LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_INITED, (mlc))
#define META_BACK_CONN_CREATING(lc)   LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_SET(lc)   LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_CLEAR(lc)   LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_CPY(lc, mlc)   LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_CREATING, (mlc))
#define META_NOT_CANDIDATE   ((ber_tag_t)0x0)
#define META_CANDIDATE   ((ber_tag_t)0x1)
#define META_BINDING   ((ber_tag_t)0x2)
#define META_RETRYING   ((ber_tag_t)0x4)
#define META_CND_ISSET(rs, f)   ( ( (rs)->sr_tag & (f) ) == (f) )
#define META_CND_SET(rs, f)   ( (rs)->sr_tag |= (f) )
#define META_CND_CLEAR(rs, f)   ( (rs)->sr_tag &= ~(f) )
#define META_CANDIDATE_RESET(rs)   ( (rs)->sr_tag = 0 )
#define META_IS_CANDIDATE(rs)   META_CND_ISSET( (rs), META_CANDIDATE )
#define META_CANDIDATE_SET(rs)   META_CND_SET( (rs), META_CANDIDATE )
#define META_CANDIDATE_CLEAR(rs)   META_CND_CLEAR( (rs), META_CANDIDATE )
#define META_IS_BINDING(rs)   META_CND_ISSET( (rs), META_BINDING )
#define META_BINDING_SET(rs)   META_CND_SET( (rs), META_BINDING )
#define META_BINDING_CLEAR(rs)   META_CND_CLEAR( (rs), META_BINDING )
#define META_IS_RETRYING(rs)   META_CND_ISSET( (rs), META_RETRYING )
#define META_RETRYING_SET(rs)   META_CND_SET( (rs), META_RETRYING )
#define META_RETRYING_CLEAR(rs)   META_CND_CLEAR( (rs), META_RETRYING )
#define lc_lcflags   msc_mscflags
#define mc_base   lc_base
#define mc_conn   mc_base.lcb_conn
#define mc_local_ndn   mc_base.lcb_local_ndn
#define mc_refcnt   mc_base.lcb_refcnt
#define mc_create_time   mc_base.lcb_create_time
#define mc_time   mc_base.lcb_time
#define META_BOUND_NONE   (-1)
#define META_BOUND_ALL   (-2)
#define ms_dn   ms_un.msu_dn
#define ms_regex   ms_un.msu_regex.msr_regex
#define ms_regex_pattern   ms_un.msu_regex.msr_regex_pattern
#define mt_idassert_mode   mt_idassert.si_mode
#define mt_idassert_authcID   mt_idassert.si_bc.sb_authcId
#define mt_idassert_authcDN   mt_idassert.si_bc.sb_binddn
#define mt_idassert_passwd   mt_idassert.si_bc.sb_cred
#define mt_idassert_authzID   mt_idassert.si_bc.sb_authzId
#define mt_idassert_authmethod   mt_idassert.si_bc.sb_method
#define mt_idassert_sasl_mech   mt_idassert.si_bc.sb_saslmech
#define mt_idassert_sasl_realm   mt_idassert.si_bc.sb_realm
#define mt_idassert_secprops   mt_idassert.si_bc.sb_secprops
#define mt_idassert_tls   mt_idassert.si_bc.sb_tls
#define mt_idassert_flags   mt_idassert.si_flags
#define mt_idassert_authz   mt_idassert.si_authz
#define META_RETRY_UNDEFINED   (-2)
#define META_RETRY_FOREVER   (-1)
#define META_RETRY_NEVER   (0)
#define META_RETRY_DEFAULT   (10)
#define META_BACK_TGT_ISSET(mt, f)   ( ( (mt)->mt_flags & (f) ) == (f) )
#define META_BACK_TGT_ISMASK(mt, m, f)   ( ( (mt)->mt_flags & (m) ) == (f) )
#define META_BACK_TGT_SAVECRED(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_SAVECRED )
#define META_BACK_TGT_USE_TLS(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_USE_TLS )
#define META_BACK_TGT_PROPAGATE_TLS(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_PROPAGATE_TLS )
#define META_BACK_TGT_TLS_CRITICAL(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_TLS_CRITICAL )
#define META_BACK_TGT_CHASE_REFERRALS(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_CHASE_REFERRALS )
#define META_BACK_TGT_T_F(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
#define META_BACK_TGT_T_F_DISCOVER(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
#define META_BACK_TGT_ABANDON(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_ABANDON )
#define META_BACK_TGT_IGNORE(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_IGNORE )
#define META_BACK_TGT_CANCEL(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_EXOP )
#define META_BACK_TGT_CANCEL_DISCOVER(mt)   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
#define META_BACK_TGT_QUARANTINE(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_QUARANTINE )
#define META_BACK_TGT_NOREFS(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_NOREFS )
#define META_BACK_TGT_NOUNDEFFILTER(mt)   META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_NOUNDEFFILTER )
#define META_BIND_TIMEOUT   LDAP_BACK_RESULT_UTIMEOUT
#define META_DNCACHE_DISABLED   (0)
#define META_DNCACHE_FOREVER   ((time_t)(-1))
#define META_DEFAULT_TARGET_NONE   (-1)
#define li_flags   mi_flags
#define META_BACK_F_ONERR_STOP   (0x01000000U)
#define META_BACK_F_ONERR_REPORT   (0x02000000U)
#define META_BACK_F_ONERR_MASK   (META_BACK_F_ONERR_STOP|META_BACK_F_ONERR_REPORT)
#define META_BACK_F_DEFER_ROOTDN_BIND   (0x04000000U)
#define META_BACK_F_PROXYAUTHZ_ALWAYS   (0x08000000U) /* users always proxyauthz */
#define META_BACK_F_PROXYAUTHZ_ANON   (0x10000000U) /* anonymous always proxyauthz */
#define META_BACK_F_PROXYAUTHZ_NOANON   (0x20000000U) /* anonymous remains anonymous */
#define META_BACK_ONERR_STOP(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_STOP )
#define META_BACK_ONERR_REPORT(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_REPORT )
#define META_BACK_ONERR_CONTINUE(mi)   ( !LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_MASK ) )
#define META_BACK_DEFER_ROOTDN_BIND(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_DEFER_ROOTDN_BIND )
#define META_BACK_PROXYAUTHZ_ALWAYS(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_ALWAYS )
#define META_BACK_PROXYAUTHZ_ANON(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_ANON )
#define META_BACK_PROXYAUTHZ_NOANON(mi)   LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_NOANON )
#define META_BACK_QUARANTINE(mi)   LDAP_BACK_ISSET( (mi), LDAP_BACK_F_QUARANTINE )
#define meta_back_release_conn(mi, mc)   meta_back_release_conn_lock( (mi), (mc), 1 )
#define META_TARGET_NONE   (-1)
#define META_TARGET_MULTIPLE   (-2)

Typedefs

typedef struct dncookie dncookie
typedef struct metasingleconn_t metasingleconn_t
typedef struct metaconn_t metaconn_t
typedef enum meta_st_t meta_st_t
typedef struct metasubtree_t metasubtree_t
typedef struct metatarget_t metatarget_t
typedef struct metadncache_t metadncache_t
typedef struct metacandidates_t metacandidates_t
typedef int(* meta_back_quarantine_f )(struct metainfo_t *, int target, void *)
typedef struct metainfo_t metainfo_t
typedef enum meta_op_type meta_op_type

Enumerations

enum  meta_st_t { META_ST_SUBTREE = LDAP_SCOPE_SUBTREE, META_ST_SUBORDINATE = LDAP_SCOPE_SUBORDINATE, META_ST_REGEX }
enum  meta_op_type { META_OP_ALLOW_MULTIPLE = 0, META_OP_REQUIRE_SINGLE, META_OP_REQUIRE_ALL }

Functions

int ldap_back_dn_massage (dncookie *dc, struct berval *dn, struct berval *res)
int ldap_back_conn_cmp (const void *c1, const void *c2)
int ldap_back_conn_dup (void *c1, void *c2)
void ldap_back_conn_free (void *c)
int mapping_cmp (const void *, const void *)
int mapping_dup (void *, void *)
void ldap_back_map_init (struct ldapmap *lm, struct ldapmapping **)
int ldap_back_mapping (struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap)
void ldap_back_map (struct ldapmap *map, struct berval *s, struct berval *m, int remap)
char * ldap_back_map_filter (struct ldapmap *at_map, struct ldapmap *oc_map, struct berval *f, int remap)
int ldap_back_map_attrs (Operation *op, struct ldapmap *at_map, AttributeName *a, int remap, char ***mapped_attrs)
int ldap_back_map_config (struct ldapmap *oc_map, struct ldapmap *at_map, const char *fname, int lineno, int argc, char **argv)
int ldap_back_filter_map_rewrite (dncookie *dc, Filter *f, struct berval *fstr, int remap, void *memctx)
int ldap_back_referral_result_rewrite (dncookie *dc, BerVarray a_vals, void *memctx)
int ldap_dnattr_rewrite (dncookie *dc, BerVarray a_vals)
int ldap_dnattr_result_rewrite (dncookie *dc, BerVarray a_vals)
SlapReplymeta_back_candidates_get (Operation *op)
metaconn_tmeta_back_getconn (Operation *op, SlapReply *rs, int *candidate, ldap_back_send_t sendok)
void meta_back_release_conn_lock (metainfo_t *mi, metaconn_t *mc, int dolock)
int meta_back_retry (Operation *op, SlapReply *rs, metaconn_t **mcp, int candidate, ldap_back_send_t sendok)
void meta_back_conn_free (void *v_mc)
int meta_back_init_one_conn (Operation *op, SlapReply *rs, metaconn_t *mc, int candidate, int ispriv, ldap_back_send_t sendok, int dolock)
void meta_back_quarantine (Operation *op, SlapReply *rs, int candidate)
int meta_back_dobind (Operation *op, SlapReply *rs, metaconn_t *mc, ldap_back_send_t sendok)
int meta_back_single_dobind (Operation *op, SlapReply *rs, metaconn_t **mcp, int candidate, ldap_back_send_t sendok, int retries, int dolock)
int meta_back_proxy_authz_cred (metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok, struct berval *binddn, struct berval *bindcred, int *method)
int meta_back_cancel (metaconn_t *mc, Operation *op, SlapReply *rs, ber_int_t msgid, int candidate, ldap_back_send_t sendok)
int meta_back_op_result (metaconn_t *mc, Operation *op, SlapReply *rs, int candidate, ber_int_t msgid, time_t timeout, ldap_back_send_t sendok)
int meta_back_controls_add (Operation *op, SlapReply *rs, metaconn_t *mc, int candidate, LDAPControl ***pctrls)
int back_meta_LTX_init_module (int argc, char *argv[])
int meta_back_conn_cmp (const void *c1, const void *c2)
int meta_back_conndn_cmp (const void *c1, const void *c2)
int meta_back_conndn_dup (void *c1, void *c2)
int meta_back_is_candidate (metatarget_t *mt, struct berval *ndn, int scope)
int meta_back_select_unique_candidate (metainfo_t *mi, struct berval *ndn)
int meta_clear_unused_candidates (Operation *op, int candidate)
int meta_clear_one_candidate (Operation *op, metaconn_t *mc, int candidate)
int meta_dncache_cmp (const void *c1, const void *c2)
int meta_dncache_dup (void *c1, void *c2)
int meta_dncache_get_target (metadncache_t *cache, struct berval *ndn)
int meta_dncache_update_entry (metadncache_t *cache, struct berval *ndn, int target)
int meta_dncache_delete_entry (metadncache_t *cache, struct berval *ndn)
void meta_dncache_free (void *entry)
int meta_subtree_destroy (metasubtree_t *ms)

Variables

LDAP_REBIND_PROC meta_back_default_rebind
LDAP_URLLIST_PROC meta_back_default_urllist

Class Documentation

struct ldapmap

Definition at line 49 of file back-meta.h.

Class Members
int drop_missing
Avlnode * map
Avlnode * remap
struct ldapmapping

Definition at line 56 of file back-meta.h.

Class Members
union ldapmapping m_dst_ref
int m_flags
union ldapmapping m_src_ref
struct ldaprwmap

Definition at line 61 of file back-meta.h.

Collaboration diagram for ldaprwmap:
Class Members
BerVarray rwm_bva_map
BerVarray rwm_bva_rewrite
unsigned rwm_flags
struct rewrite_info * rwm_rw
BerVarray rwm_suffix_massage
struct dncookie

Definition at line 81 of file back-meta.h.

Collaboration diagram for dncookie:
Class Members
Connection * conn
char * ctx
int normalized
SlapReply * rs
struct ldaprwmap * rwmap
struct metatarget_t * target
int tofrom
struct metasingleconn_t

Definition at line 204 of file back-meta.h.

Class Members
LDAP * msc_ld
unsigned msc_mscflags
time_t msc_time
struct metasubtree_t

Definition at line 271 of file back-meta.h.

Collaboration diagram for metasubtree_t:
Class Members
struct metasubtree_t * ms_next
meta_st_t ms_type
union metasubtree_t ms_un
struct metatarget_t

Definition at line 287 of file back-meta.h.

Collaboration diagram for metatarget_t:
Class Members
unsigned mt_flags
slap_idassert_t mt_idassert
sig_atomic_t mt_isquarantined
time_t mt_network_timeout
int mt_nretries
slap_retry_info_t mt_quarantine
ldap_pvt_thread_mutex_t mt_quarantine_mutex
LDAP_REBIND_PROC * mt_rebind_f
slap_mask_t mt_rep_flags
int mt_scope
metasubtree_t * mt_subtree
int mt_subtree_exclude
time_t mt_timeout
slap_bindconf mt_tls
char * mt_uri
ldap_pvt_thread_mutex_t mt_uri_mutex
LDAP_URLLIST_PROC * mt_urllist_f
void * mt_urllist_p
int mt_version
struct metadncache_t

Definition at line 389 of file back-meta.h.

Class Members
ldap_pvt_thread_mutex_t mutex
Avlnode * tree
time_t ttl
struct metacandidates_t

Definition at line 398 of file back-meta.h.

Collaboration diagram for metacandidates_t:
Class Members
SlapReply * mc_candidates
int mc_ntargets
struct metainfo_t

Definition at line 408 of file back-meta.h.

Collaboration diagram for metainfo_t:
Class Members
metadncache_t mi_cache
metacandidates_t * mi_candidates
struct metainfo_t mi_conn_priv
int mi_conn_priv_max
time_t mi_conn_ttl
ldap_avl_info_t mi_conninfo
int mi_defaulttarget
unsigned mi_flags
time_t mi_idle_timeout
ldap_extra_t * mi_ldap_extra
time_t mi_network_timeout
int mi_nretries
int mi_ntargets
slap_retry_info_t mi_quarantine
meta_back_quarantine_f mi_quarantine_f
void * mi_quarantine_p
LDAP_REBIND_PROC * mi_rebind_f
metatarget_t ** mi_targets
time_t mi_timeout
LDAP_URLLIST_PROC * mi_urllist_f
int mi_version
union metasubtree_t.ms_un

Definition at line 273 of file back-meta.h.

Class Members
ms_un msu_regex
struct metasubtree_t.ms_un.msu_regex

Definition at line 275 of file back-meta.h.

Class Members
regex_t msr_regex
char * msr_regex_pattern
struct metainfo_t.mi_conn_priv

Definition at line 425 of file back-meta.h.

Class Members
int mic_num

Define Documentation

#define BACKLDAP_MAP   0

Definition at line 110 of file back-meta.h.

#define BACKLDAP_REMAP   1

Definition at line 111 of file back-meta.h.

#define lc_lcflags   msc_mscflags

Definition at line 227 of file back-meta.h.

#define li_flags   mi_flags

Definition at line 437 of file back-meta.h.

#define mc_base   lc_base

Definition at line 232 of file back-meta.h.

#define mc_conn   mc_base.lcb_conn

Definition at line 233 of file back-meta.h.

#define mc_create_time   mc_base.lcb_create_time

Definition at line 236 of file back-meta.h.

#define mc_local_ndn   mc_base.lcb_local_ndn

Definition at line 234 of file back-meta.h.

#define mc_refcnt   mc_base.lcb_refcnt

Definition at line 235 of file back-meta.h.

#define mc_time   mc_base.lcb_time

Definition at line 237 of file back-meta.h.

Definition at line 192 of file back-meta.h.

Definition at line 194 of file back-meta.h.

Definition at line 195 of file back-meta.h.

Definition at line 193 of file back-meta.h.

Definition at line 188 of file back-meta.h.

Definition at line 190 of file back-meta.h.

#define META_BACK_CONN_INITED_CPY (   lc,
  mlc 
)    LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_INITED, (mlc))

Definition at line 191 of file back-meta.h.

Definition at line 189 of file back-meta.h.

Definition at line 451 of file back-meta.h.

#define META_BACK_F_DEFER_ROOTDN_BIND   (0x04000000U)

Definition at line 442 of file back-meta.h.

Definition at line 441 of file back-meta.h.

#define META_BACK_F_ONERR_REPORT   (0x02000000U)

Definition at line 440 of file back-meta.h.

#define META_BACK_F_ONERR_STOP   (0x01000000U)

Definition at line 439 of file back-meta.h.

#define META_BACK_F_PROXYAUTHZ_ALWAYS   (0x08000000U) /* users always proxyauthz */

Definition at line 443 of file back-meta.h.

#define META_BACK_F_PROXYAUTHZ_ANON   (0x10000000U) /* anonymous always proxyauthz */

Definition at line 444 of file back-meta.h.

#define META_BACK_F_PROXYAUTHZ_NOANON   (0x20000000U) /* anonymous remains anonymous */

Definition at line 445 of file back-meta.h.

#define META_BACK_FCONN_CREATING   (0x00200000U)

Definition at line 186 of file back-meta.h.

#define META_BACK_FCONN_INITED   (0x00100000U)

Definition at line 185 of file back-meta.h.

#define META_BACK_ONERR_CONTINUE (   mi)    ( !LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_MASK ) )

Definition at line 449 of file back-meta.h.

Definition at line 448 of file back-meta.h.

Definition at line 447 of file back-meta.h.

#define META_BACK_PRINT_CONNTREE   0

Definition at line 45 of file back-meta.h.

Definition at line 452 of file back-meta.h.

Definition at line 453 of file back-meta.h.

Definition at line 454 of file back-meta.h.

Definition at line 456 of file back-meta.h.

#define meta_back_release_conn (   mi,
  mc 
)    meta_back_release_conn_lock( (mi), (mc), 1 )

Definition at line 496 of file back-meta.h.

Definition at line 353 of file back-meta.h.

Definition at line 355 of file back-meta.h.

Definition at line 356 of file back-meta.h.

Definition at line 348 of file back-meta.h.

Definition at line 354 of file back-meta.h.

#define META_BACK_TGT_ISMASK (   mt,
  m,
  f 
)    ( ( (mt)->mt_flags & (m) ) == (f) )

Definition at line 340 of file back-meta.h.

#define META_BACK_TGT_ISSET (   mt,
  f 
)    ( ( (mt)->mt_flags & (f) ) == (f) )

Definition at line 339 of file back-meta.h.

Definition at line 364 of file back-meta.h.

Definition at line 365 of file back-meta.h.

Definition at line 345 of file back-meta.h.

Definition at line 357 of file back-meta.h.

Definition at line 342 of file back-meta.h.

Definition at line 350 of file back-meta.h.

Definition at line 351 of file back-meta.h.

Definition at line 346 of file back-meta.h.

Definition at line 344 of file back-meta.h.

Definition at line 385 of file back-meta.h.

#define META_BINDING   ((ber_tag_t)0x2)

Definition at line 201 of file back-meta.h.

#define META_BINDING_CLEAR (   rs)    META_CND_CLEAR( (rs), META_BINDING )

Definition at line 215 of file back-meta.h.

#define META_BINDING_SET (   rs)    META_CND_SET( (rs), META_BINDING )

Definition at line 214 of file back-meta.h.

#define META_BOUND_ALL   (-2)

Definition at line 251 of file back-meta.h.

#define META_BOUND_NONE   (-1)

Definition at line 250 of file back-meta.h.

#define META_CANDIDATE   ((ber_tag_t)0x1)

Definition at line 200 of file back-meta.h.

Definition at line 212 of file back-meta.h.

#define META_CANDIDATE_RESET (   rs)    ( (rs)->sr_tag = 0 )

Definition at line 209 of file back-meta.h.

#define META_CANDIDATE_SET (   rs)    META_CND_SET( (rs), META_CANDIDATE )

Definition at line 211 of file back-meta.h.

#define META_CND_CLEAR (   rs,
  f 
)    ( (rs)->sr_tag &= ~(f) )

Definition at line 207 of file back-meta.h.

#define META_CND_ISSET (   rs,
  f 
)    ( ( (rs)->sr_tag & (f) ) == (f) )

Definition at line 205 of file back-meta.h.

#define META_CND_SET (   rs,
  f 
)    ( (rs)->sr_tag |= (f) )

Definition at line 206 of file back-meta.h.

#define META_DEFAULT_TARGET_NONE   (-1)

Definition at line 411 of file back-meta.h.

#define META_DNCACHE_DISABLED   (0)

Definition at line 393 of file back-meta.h.

#define META_DNCACHE_FOREVER   ((time_t)(-1))

Definition at line 394 of file back-meta.h.

#define META_IS_BINDING (   rs)    META_CND_ISSET( (rs), META_BINDING )

Definition at line 213 of file back-meta.h.

Definition at line 210 of file back-meta.h.

#define META_IS_RETRYING (   rs)    META_CND_ISSET( (rs), META_RETRYING )

Definition at line 216 of file back-meta.h.

#define META_NOT_CANDIDATE   ((ber_tag_t)0x0)

Definition at line 199 of file back-meta.h.

#define META_RETRY_DEFAULT   (10)

Definition at line 330 of file back-meta.h.

#define META_RETRY_FOREVER   (-1)

Definition at line 328 of file back-meta.h.

#define META_RETRY_NEVER   (0)

Definition at line 329 of file back-meta.h.

#define META_RETRY_UNDEFINED   (-2)

Definition at line 327 of file back-meta.h.

#define META_RETRYING   ((ber_tag_t)0x4)

Definition at line 202 of file back-meta.h.

Definition at line 218 of file back-meta.h.

#define META_RETRYING_SET (   rs)    META_CND_SET( (rs), META_RETRYING )

Definition at line 217 of file back-meta.h.

#define META_TARGET_MULTIPLE   (-2)

Definition at line 647 of file back-meta.h.

#define META_TARGET_NONE   (-1)

Definition at line 646 of file back-meta.h.

#define ms_dn   ms_un.msu_dn

Definition at line 280 of file back-meta.h.

#define ms_regex   ms_un.msu_regex.msr_regex

Definition at line 281 of file back-meta.h.

#define ms_regex_pattern   ms_un.msu_regex.msr_regex_pattern

Definition at line 282 of file back-meta.h.

#define mt_idassert_authcDN   mt_idassert.si_bc.sb_binddn

Definition at line 315 of file back-meta.h.

#define mt_idassert_authcID   mt_idassert.si_bc.sb_authcId

Definition at line 314 of file back-meta.h.

#define mt_idassert_authmethod   mt_idassert.si_bc.sb_method

Definition at line 318 of file back-meta.h.

#define mt_idassert_authz   mt_idassert.si_authz

Definition at line 324 of file back-meta.h.

#define mt_idassert_authzID   mt_idassert.si_bc.sb_authzId

Definition at line 317 of file back-meta.h.

#define mt_idassert_flags   mt_idassert.si_flags

Definition at line 323 of file back-meta.h.

#define mt_idassert_mode   mt_idassert.si_mode

Definition at line 313 of file back-meta.h.

#define mt_idassert_passwd   mt_idassert.si_bc.sb_cred

Definition at line 316 of file back-meta.h.

#define mt_idassert_sasl_mech   mt_idassert.si_bc.sb_saslmech

Definition at line 319 of file back-meta.h.

#define mt_idassert_sasl_realm   mt_idassert.si_bc.sb_realm

Definition at line 320 of file back-meta.h.

#define mt_idassert_secprops   mt_idassert.si_bc.sb_secprops

Definition at line 321 of file back-meta.h.

#define mt_idassert_tls   mt_idassert.si_bc.sb_tls

Definition at line 322 of file back-meta.h.


Typedef Documentation

typedef struct dncookie dncookie
typedef int(* meta_back_quarantine_f)(struct metainfo_t *, int target, void *)

Definition at line 406 of file back-meta.h.

typedef enum meta_op_type meta_op_type
typedef enum meta_st_t meta_st_t
typedef struct metaconn_t metaconn_t
typedef struct metadncache_t metadncache_t
typedef struct metainfo_t metainfo_t
typedef struct metasubtree_t metasubtree_t
typedef struct metatarget_t metatarget_t

Enumeration Type Documentation

Enumerator:
META_OP_ALLOW_MULTIPLE 
META_OP_REQUIRE_SINGLE 
META_OP_REQUIRE_ALL 

Definition at line 475 of file back-meta.h.

enum meta_st_t
Enumerator:
META_ST_SUBTREE 
META_ST_SUBORDINATE 
META_ST_REGEX 

Definition at line 262 of file back-meta.h.

                       {
#if 0 /* todo */
       META_ST_EXACT = LDAP_SCOPE_BASE,
#endif
       META_ST_SUBTREE = LDAP_SCOPE_SUBTREE,
       META_ST_SUBORDINATE = LDAP_SCOPE_SUBORDINATE,
       META_ST_REGEX /* last + 1 */
} meta_st_t;

Function Documentation

int back_meta_LTX_init_module ( int  argc,
char *  argv[] 
)
int ldap_back_conn_cmp ( const void c1,
const void c2 
)

Definition at line 460 of file bind.c.

{
       const ldapconn_t     *lc1 = (const ldapconn_t *)c1;
       const ldapconn_t     *lc2 = (const ldapconn_t *)c2;

       /* For shared sessions, conn is NULL. Only explicitly
        * bound sessions will have non-NULL conn.
        */
       return SLAP_PTRCMP( lc1->lc_conn, lc2->lc_conn );
}

Here is the caller graph for this function:

int ldap_back_conn_dup ( void c1,
void c2 
)

Definition at line 258 of file init.c.

{
       ldapconn_t    *lc = v_lc;

       if ( lc->lc_ld != NULL ) {  
              ldap_unbind_ext( lc->lc_ld, NULL, NULL );
       }
       if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
              ch_free( lc->lc_bound_ndn.bv_val );
       }
       if ( !BER_BVISNULL( &lc->lc_cred ) ) {
              memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len );
              ch_free( lc->lc_cred.bv_val );
       }
       if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
              ch_free( lc->lc_local_ndn.bv_val );
       }
       lc->lc_q.tqe_prev = NULL;
       lc->lc_q.tqe_next = NULL;
       ch_free( lc );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_dn_massage ( dncookie dc,
struct berval dn,
struct berval res 
)

Definition at line 120 of file suffixmassage.c.

{
       int     i, src, dst;
       struct berval pretty = {0,NULL}, *dn = odn;

       assert( res != NULL );

       if ( dn == NULL ) {
              res->bv_val = NULL;
              res->bv_len = 0;
              return 0;
       }
       if ( dc->target->mt_rwmap.rwm_suffix_massage == NULL ) {
              *res = *dn;
              return 0;
       }

       if ( dc->tofrom ) {
              src = 0 + dc->normalized;
              dst = 2 + dc->normalized;
       } else {
              src = 2 + dc->normalized;
              dst = 0 + dc->normalized;
              /* DN from remote server may be in arbitrary form.
               * Pretty it so we can parse reliably.
               */
              dnPretty( NULL, dn, &pretty, NULL );
              if (pretty.bv_val) dn = &pretty;
       }

       for ( i = 0;
              dc->target->mt_rwmap.rwm_suffix_massage[i].bv_val != NULL;
              i += 4 ) {
              int aliasLength = dc->target->mt_rwmap.rwm_suffix_massage[i+src].bv_len;
              int diff = dn->bv_len - aliasLength;

              if ( diff < 0 ) {
                     /* alias is longer than dn */
                     continue;
              } else if ( diff > 0 && ( !DN_SEPARATOR(dn->bv_val[diff-1]))) {
                     /* boundary is not at a DN separator */
                     continue;
                     /* At a DN Separator */
              }

              if ( !strcmp( dc->target->mt_rwmap.rwm_suffix_massage[i+src].bv_val, &dn->bv_val[diff] ) ) {
                     res->bv_len = diff + dc->target->mt_rwmap.rwm_suffix_massage[i+dst].bv_len;
                     res->bv_val = ch_malloc( res->bv_len + 1 );
                     strncpy( res->bv_val, dn->bv_val, diff );
                     strcpy( &res->bv_val[diff], dc->target->mt_rwmap.rwm_suffix_massage[i+dst].bv_val );
                     Debug( LDAP_DEBUG_ARGS,
                            "ldap_back_dn_massage:"
                            " converted \"%s\" to \"%s\"\n",
                            BER_BVISNULL( dn ) ? "" : dn->bv_val,
                            BER_BVISNULL( res ) ? "" : res->bv_val, 0 );
                     break;
              }
       }
       if (pretty.bv_val) {
              ch_free(pretty.bv_val);
              dn = odn;
       }
       /* Nothing matched, just return the original DN */
       if (res->bv_val == NULL) {
              *res = *dn;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_filter_map_rewrite ( dncookie dc,
Filter f,
struct berval fstr,
int  remap,
void memctx 
)

Definition at line 622 of file map.c.

{
       int           rc;
       dncookie      fdc;
       struct berval ftmp;
       static char   *dmy = "";

       rc = ldap_back_int_filter_map_rewrite( dc, f, fstr, remap, memctx );

#ifdef ENABLE_REWRITE
       if ( rc != LDAP_SUCCESS ) {
              return rc;
       }

       fdc = *dc;
       ftmp = *fstr;

       fdc.ctx = "searchFilter";
       
       switch ( rewrite_session( fdc.target->mt_rwmap.rwm_rw, fdc.ctx,
                            ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : dmy ),
                            fdc.conn, &fstr->bv_val ) )
       {
       case REWRITE_REGEXEC_OK:
              if ( !BER_BVISNULL( fstr ) ) {
                     fstr->bv_len = strlen( fstr->bv_val );

              } else {
                     *fstr = ftmp;
              }
              Debug( LDAP_DEBUG_ARGS,
                     "[rw] %s: \"%s\" -> \"%s\"\n",
                     fdc.ctx, BER_BVISNULL( &ftmp ) ? "" : ftmp.bv_val,
                     BER_BVISNULL( fstr ) ? "" : fstr->bv_val );             
              rc = LDAP_SUCCESS;
              break;
              
       case REWRITE_REGEXEC_UNWILLING:
              if ( fdc.rs ) {
                     fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                     fdc.rs->sr_text = "Operation not allowed";
              }
              rc = LDAP_UNWILLING_TO_PERFORM;
              break;
                     
       case REWRITE_REGEXEC_ERR:
              if ( fdc.rs ) {
                     fdc.rs->sr_err = LDAP_OTHER;
                     fdc.rs->sr_text = "Rewrite error";
              }
              rc = LDAP_OTHER;
              break;
       }

       if ( fstr->bv_val == dmy ) {
              BER_BVZERO( fstr );

       } else if ( fstr->bv_val != ftmp.bv_val ) {
              /* NOTE: need to realloc mapped filter on slab
               * and free the original one, until librewrite
               * becomes slab-aware
               */
              ber_dupbv_x( &ftmp, fstr, memctx );
              ch_free( fstr->bv_val );
              *fstr = ftmp;
       }
#endif /* ENABLE_REWRITE */

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ldap_back_map ( struct ldapmap map,
struct berval s,
struct berval m,
int  remap 
)

Definition at line 145 of file map.c.

{
       struct ldapmapping *mapping;
       int drop_missing;

       /* map->map may be NULL when mapping is configured,
        * but map->remap can't */
       if ( map->remap == NULL ) {
              *bv = *s;
              return;
       }

       BER_BVZERO( bv );
       drop_missing = ldap_back_mapping( map, s, &mapping, remap );
       if ( mapping != NULL ) {
              if ( !BER_BVISNULL( &mapping->dst ) ) {
                     *bv = mapping->dst;
              }
              return;
       }

       if ( !drop_missing ) {
              *bv = *s;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_map_attrs ( Operation op,
struct ldapmap at_map,
AttributeName a,
int  remap,
char ***  mapped_attrs 
)

Definition at line 173 of file map.c.

{
       int i, x, j;
       char **na;
       struct berval mapped;

       if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) {
              *mapped_attrs = NULL;
              return LDAP_SUCCESS;
       }

       i = 0;
       if ( an != NULL ) {
              for ( ; !BER_BVISNULL( &an[i].an_name ); i++ )
                     /*  */ ;
       }

       x = 0;
       if ( op->o_bd->be_extra_anlist != NULL ) {
              for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
                     /*  */ ;
       }

       assert( i > 0 || x > 0 );
       
       na = (char **)ber_memcalloc_x( i + x + 1, sizeof(char *), op->o_tmpmemctx );
       if ( na == NULL ) {
              *mapped_attrs = NULL;
              return LDAP_NO_MEMORY;
       }

       j = 0;
       if ( i > 0 ) {
              for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
                     ldap_back_map( at_map, &an[i].an_name, &mapped, remap );
                     if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
                            na[j++] = mapped.bv_val;
                     }
              }
       }

       if ( x > 0 ) {
              for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) {
                     if ( op->o_bd->be_extra_anlist[x].an_desc &&
                            ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, an ) )
                     {
                            continue;
                     }

                     ldap_back_map( at_map, &op->o_bd->be_extra_anlist[x].an_name, &mapped, remap );
                     if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
                            na[j++] = mapped.bv_val;
                     }
              }
       }

       if ( j == 0 && ( i > 0 || x > 0 ) ) {
              na[j++] = LDAP_NO_ATTRS;
       }
       na[j] = NULL;

       *mapped_attrs = na;

       return LDAP_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_map_config ( struct ldapmap oc_map,
struct ldapmap at_map,
const char *  fname,
int  lineno,
int  argc,
char **  argv 
)

Definition at line 1831 of file config.c.

{
       struct ldapmap              *map;
       struct ldapmapping   *mapping;
       char                 *src, *dst;
       int                  is_oc = 0;

       if ( argc < 3 || argc > 4 ) {
              Debug( LDAP_DEBUG_ANY,
       "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
                     fname, lineno, 0 );
              return 1;
       }

       if ( strcasecmp( argv[ 1 ], "objectclass" ) == 0 ) {
              map = oc_map;
              is_oc = 1;

       } else if ( strcasecmp( argv[ 1 ], "attribute" ) == 0 ) {
              map = at_map;

       } else {
              Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is "
                     "\"map {objectclass | attribute} [<local> | *] "
                     "{<foreign> | *}\"\n",
                     fname, lineno, 0 );
              return 1;
       }

       if ( !is_oc && map->map == NULL ) {
              /* only init if required */
              ldap_back_map_init( map, &mapping );
       }

       if ( strcmp( argv[ 2 ], "*" ) == 0 ) {
              if ( argc < 4 || strcmp( argv[ 3 ], "*" ) == 0 ) {
                     map->drop_missing = ( argc < 4 );
                     goto success_return;
              }
              src = dst = argv[ 3 ];

       } else if ( argc < 4 ) {
              src = "";
              dst = argv[ 2 ];

       } else {
              src = argv[ 2 ];
              dst = ( strcmp( argv[ 3 ], "*" ) == 0 ? src : argv[ 3 ] );
       }

       if ( ( map == at_map )
              && ( strcasecmp( src, "objectclass" ) == 0
                     || strcasecmp( dst, "objectclass" ) == 0 ) )
       {
              Debug( LDAP_DEBUG_ANY,
                     "%s: line %d: objectclass attribute cannot be mapped\n",
                     fname, lineno, 0 );
       }

       mapping = (struct ldapmapping *)ch_calloc( 2,
              sizeof(struct ldapmapping) );
       if ( mapping == NULL ) {
              Debug( LDAP_DEBUG_ANY,
                     "%s: line %d: out of memory\n",
                     fname, lineno, 0 );
              return 1;
       }
       ber_str2bv( src, 0, 1, &mapping[ 0 ].src );
       ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst );
       mapping[ 1 ].src = mapping[ 0 ].dst;
       mapping[ 1 ].dst = mapping[ 0 ].src;

       /*
        * schema check
        */
       if ( is_oc ) {
              if ( src[ 0 ] != '\0' ) {
                     if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) {
                            Debug( LDAP_DEBUG_ANY,
       "%s: line %d: warning, source objectClass '%s' "
       "should be defined in schema\n",
                                   fname, lineno, src );

                            /*
                             * FIXME: this should become an err
                             */
                            goto error_return;
                     }
              }

              if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) {
                     Debug( LDAP_DEBUG_ANY,
       "%s: line %d: warning, destination objectClass '%s' "
       "is not defined in schema\n",
                            fname, lineno, dst );
              }
       } else {
              int                  rc;
              const char           *text = NULL;
              AttributeDescription *ad = NULL;

              if ( src[ 0 ] != '\0' ) {
                     rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text );
                     if ( rc != LDAP_SUCCESS ) {
                            Debug( LDAP_DEBUG_ANY,
       "%s: line %d: warning, source attributeType '%s' "
       "should be defined in schema\n",
                                   fname, lineno, src );

                            /*
                             * FIXME: this should become an err
                             */
                            /*
                             * we create a fake "proxied" ad 
                             * and add it here.
                             */

                            rc = slap_bv2undef_ad( &mapping[ 0 ].src,
                                          &ad, &text, SLAP_AD_PROXIED );
                            if ( rc != LDAP_SUCCESS ) {
                                   char   buf[ SLAP_TEXT_BUFLEN ];

                                   snprintf( buf, sizeof( buf ),
                                          "source attributeType \"%s\": %d (%s)",
                                          src, rc, text ? text : "" );
                                   Debug( LDAP_DEBUG_ANY,
                                          "%s: line %d: %s\n",
                                          fname, lineno, buf );
                                   goto error_return;
                            }
                     }

                     ad = NULL;
              }

              rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text );
              if ( rc != LDAP_SUCCESS ) {
                     Debug( LDAP_DEBUG_ANY,
       "%s: line %d: warning, destination attributeType '%s' "
       "is not defined in schema\n",
                            fname, lineno, dst );

                     /*
                      * we create a fake "proxied" ad 
                      * and add it here.
                      */

                     rc = slap_bv2undef_ad( &mapping[ 0 ].dst,
                                   &ad, &text, SLAP_AD_PROXIED );
                     if ( rc != LDAP_SUCCESS ) {
                            char   buf[ SLAP_TEXT_BUFLEN ];

                            snprintf( buf, sizeof( buf ),
                                   "source attributeType \"%s\": %d (%s)\n",
                                   dst, rc, text ? text : "" );
                            Debug( LDAP_DEBUG_ANY,
                                   "%s: line %d: %s\n",
                                   fname, lineno, buf );
                            return 1;
                     }
              }
       }

       if ( (src[ 0 ] != '\0' && avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL)
                     || avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL)
       {
              Debug( LDAP_DEBUG_ANY,
                     "%s: line %d: duplicate mapping found.\n",
                     fname, lineno, 0 );
              goto error_return;
       }

       if ( src[ 0 ] != '\0' ) {
              avl_insert( &map->map, (caddr_t)&mapping[ 0 ],
                                   mapping_cmp, mapping_dup );
       }
       avl_insert( &map->remap, (caddr_t)&mapping[ 1 ],
                            mapping_cmp, mapping_dup );

success_return:;
       return 0;

error_return:;
       if ( mapping ) {
              ch_free( mapping[ 0 ].src.bv_val );
              ch_free( mapping[ 0 ].dst.bv_val );
              ch_free( mapping );
       }

       return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* ldap_back_map_filter ( struct ldapmap at_map,
struct ldapmap oc_map,
struct berval f,
int  remap 
)
void ldap_back_map_init ( struct ldapmap lm,
struct ldapmapping **   
)

Definition at line 84 of file map.c.

{
       struct ldapmapping *mapping;

       assert( m != NULL );

       *m = NULL;

       mapping = (struct ldapmapping *)ch_calloc( 2, 
                     sizeof( struct ldapmapping ) );
       if ( mapping == NULL ) {
              return;
       }

       ber_str2bv( "objectclass", STRLENOF("objectclass"), 1, &mapping[0].src);
       ber_dupbv( &mapping[0].dst, &mapping[0].src );
       mapping[1].src = mapping[0].src;
       mapping[1].dst = mapping[0].dst;

       avl_insert( &lm->map, (caddr_t)&mapping[0], 
                     mapping_cmp, mapping_dup );
       avl_insert( &lm->remap, (caddr_t)&mapping[1], 
                     mapping_cmp, mapping_dup );
       *m = mapping;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_mapping ( struct ldapmap map,
struct berval s,
struct ldapmapping **  m,
int  remap 
)

Definition at line 111 of file map.c.

{
       Avlnode *tree;
       struct ldapmapping fmapping;

       assert( m != NULL );

       /* let special attrnames slip through (ITS#5760) */
       if ( bvmatch( s, slap_bv_no_attrs )
              || bvmatch( s, slap_bv_all_user_attrs )
              || bvmatch( s, slap_bv_all_operational_attrs ) )
       {
              *m = NULL;
              return 0;
       }

       if ( remap == BACKLDAP_REMAP ) {
              tree = map->remap;

       } else {
              tree = map->map;
       }

       fmapping.src = *s;
       *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
       if ( *m == NULL ) {
              return map->drop_missing;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_back_referral_result_rewrite ( dncookie dc,
BerVarray  a_vals,
void memctx 
)

Definition at line 699 of file map.c.

{
       int           i, last;

       assert( dc != NULL );
       assert( a_vals != NULL );

       for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ )
              ;
       last--;

       for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) {
              struct berval dn,
                            olddn = BER_BVNULL;
              int           rc;
              LDAPURLDesc   *ludp;

              rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp );
              if ( rc != LDAP_URL_SUCCESS ) {
                     /* leave attr untouched if massage failed */
                     continue;
              }

              /* FIXME: URLs like "ldap:///dc=suffix" if passed
               * thru ldap_url_parse() and ldap_url_desc2str()
               * get rewritten as "ldap:///dc=suffix??base";
               * we don't want this to occur... */
              if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
                     ludp->lud_scope = LDAP_SCOPE_DEFAULT;
              }

              ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
              
              rc = ldap_back_dn_massage( dc, &olddn, &dn );
              switch ( rc ) {
              case LDAP_UNWILLING_TO_PERFORM:
                     /*
                      * FIXME: need to check if it may be considered 
                      * legal to trim values when adding/modifying;
                      * it should be when searching (e.g. ACLs).
                      */
                     ber_memfree( a_vals[ i ].bv_val );
                     if ( last > i ) {
                            a_vals[ i ] = a_vals[ last ];
                     }
                     BER_BVZERO( &a_vals[ last ] );
                     last--;
                     i--;
                     break;

              default:
                     /* leave attr untouched if massage failed */
                     if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val )
                     {
                            char   *newurl;

                            ludp->lud_dn = dn.bv_val;
                            newurl = ldap_url_desc2str( ludp );
                            free( dn.bv_val );
                            if ( newurl == NULL ) {
                                   /* FIXME: leave attr untouched
                                    * even if ldap_url_desc2str failed...
                                    */
                                   break;
                            }

                            ber_memfree_x( a_vals[ i ].bv_val, memctx );
                            ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx );
                            ber_memfree( newurl );
                            ludp->lud_dn = olddn.bv_val;
                     }
                     break;
              }

              ldap_free_urldesc( ludp );
       }

       return 0;
}

Here is the call graph for this function:

Definition at line 835 of file map.c.

{
       struct berval bv;
       int           i, last;

       assert( a_vals != NULL );

       for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
              ;
       last--;

       for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
              switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
              case LDAP_UNWILLING_TO_PERFORM:
                     /*
                      * FIXME: need to check if it may be considered 
                      * legal to trim values when adding/modifying;
                      * it should be when searching (e.g. ACLs).
                      */
                     ber_memfree( a_vals[i].bv_val );
                     if ( last > i ) {
                            a_vals[i] = a_vals[last];
                     }
                     BER_BVZERO( &a_vals[last] );
                     last--;
                     break;

              default:
                     /* leave attr untouched if massage failed */
                     if ( !BER_BVISNULL( &bv ) && a_vals[i].bv_val != bv.bv_val ) {
                            ber_memfree( a_vals[i].bv_val );
                            a_vals[i] = bv;
                     }
                     break;
              }
       }

       return 0;
}

Here is the call graph for this function:

int ldap_dnattr_rewrite ( dncookie dc,
BerVarray  a_vals 
)

Definition at line 791 of file map.c.

{
       struct berval bv;
       int           i, last;

       assert( a_vals != NULL );

       for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
              ;
       last--;

       for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
              switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
              case LDAP_UNWILLING_TO_PERFORM:
                     /*
                      * FIXME: need to check if it may be considered 
                      * legal to trim values when adding/modifying;
                      * it should be when searching (e.g. ACLs).
                      */
                     ch_free( a_vals[i].bv_val );
                     if ( last > i ) {
                            a_vals[i] = a_vals[last];
                     }
                     BER_BVZERO( &a_vals[last] );
                     last--;
                     break;

              default:
                     /* leave attr untouched if massage failed */
                     if ( !BER_BVISNULL( &bv ) && bv.bv_val != a_vals[i].bv_val ) {
                            ch_free( a_vals[i].bv_val );
                            a_vals[i] = bv;
                     }
                     break;
              }
       }
       
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mapping_cmp ( const void ,
const void  
)

Definition at line 65 of file map.c.

{
       struct ldapmapping *map1 = (struct ldapmapping *)c1;
       struct ldapmapping *map2 = (struct ldapmapping *)c2;
       int rc = map1->src.bv_len - map2->src.bv_len;
       if (rc) return rc;
       return ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mapping_dup ( void ,
void  
)

Definition at line 75 of file map.c.

{
       struct ldapmapping *map1 = (struct ldapmapping *)c1;
       struct ldapmapping *map2 = (struct ldapmapping *)c2;

       return ( ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) == 0 ) ? -1 : 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_cancel ( metaconn_t mc,
Operation op,
SlapReply rs,
ber_int_t  msgid,
int  candidate,
ldap_back_send_t  sendok 
)

Definition at line 917 of file bind.c.

{
       metainfo_t           *mi = (metainfo_t *)op->o_bd->be_private;

       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];

       int                  rc = LDAP_OTHER;

       Debug( LDAP_DEBUG_TRACE, ">>> %s meta_back_cancel[%d] msgid=%d\n",
              op->o_log_prefix, candidate, msgid );

       /* default behavior */
       if ( META_BACK_TGT_ABANDON( mt ) ) {
              rc = ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );

       } else if ( META_BACK_TGT_IGNORE( mt ) ) {
              rc = ldap_pvt_discard( msc->msc_ld, msgid );

       } else if ( META_BACK_TGT_CANCEL( mt ) ) {
              rc = ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL );

       } else {
              assert( 0 );
       }

       Debug( LDAP_DEBUG_TRACE, "<<< %s meta_back_cancel[%d] err=%d\n",
              op->o_log_prefix, candidate, rc );

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 983 of file conn.c.

{
       metainfo_t           *mi = ( metainfo_t * )op->o_bd->be_private;
       metacandidates_t     *mc;

       if ( op->o_threadctx ) {
              void          *data = NULL;

              ldap_pvt_thread_pool_getkey( op->o_threadctx,
                            &meta_back_candidates_dummy, &data, NULL );
              mc = (metacandidates_t *)data;

       } else {
              mc = mi->mi_candidates;
       }

       if ( mc == NULL ) {
              mc = ch_calloc( sizeof( metacandidates_t ), 1 );
              mc->mc_ntargets = mi->mi_ntargets;
              mc->mc_candidates = ch_calloc( sizeof( SlapReply ), mc->mc_ntargets );
              if ( op->o_threadctx ) {
                     void          *data = NULL;

                     data = (void *)mc;
                     ldap_pvt_thread_pool_setkey( op->o_threadctx,
                                   &meta_back_candidates_dummy, data,
                                   meta_back_candidates_keyfree,
                                   NULL, NULL );

              } else {
                     mi->mi_candidates = mc;
              }

       } else if ( mc->mc_ntargets < mi->mi_ntargets ) {
              /* NOTE: in the future, may want to allow back-config
               * to add/remove targets from back-meta... */
              mc->mc_candidates = ch_realloc( mc->mc_candidates,
                            sizeof( SlapReply ) * mi->mi_ntargets );
              memset( &mc->mc_candidates[ mc->mc_ntargets ], 0,
                     sizeof( SlapReply ) * ( mi->mi_ntargets - mc->mc_ntargets ) );
              mc->mc_ntargets = mi->mi_ntargets;
       }

       return mc->mc_candidates;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_conn_cmp ( const void c1,
const void c2 
)

Definition at line 101 of file conn.c.

{
       metaconn_t    *mc1 = ( metaconn_t * )c1;
        metaconn_t   *mc2 = ( metaconn_t * )c2;
       
       /* For shared sessions, conn is NULL. Only explicitly
        * bound sessions will have non-NULL conn.
        */
       return SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
}

Here is the caller graph for this function:

Definition at line 268 of file init.c.

{
       metaconn_t           *mc = v_mc;
       int                  ntargets;

       assert( mc != NULL );
       assert( mc->mc_refcnt == 0 );

       /* at least one must be present... */
       ntargets = mc->mc_info->mi_ntargets;
       assert( ntargets > 0 );

       for ( ; ntargets--; ) {
              (void)meta_clear_one_candidate( NULL, mc, ntargets );
       }

       if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
              free( mc->mc_local_ndn.bv_val );
       }

       free( mc );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_conndn_cmp ( const void c1,
const void c2 
)

Definition at line 44 of file conn.c.

{
       metaconn_t    *mc1 = ( metaconn_t * )c1;
        metaconn_t   *mc2 = ( metaconn_t * )c2;
       int           rc;
       
       /* If local DNs don't match, it is definitely not a match */
       /* For shared sessions, conn is NULL. Only explicitly
        * bound sessions will have non-NULL conn.
        */
       rc = SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
       if ( rc == 0 ) {
              rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
       }

       return rc;
}

Here is the caller graph for this function:

int meta_back_conndn_dup ( void c1,
void c2 
)

Definition at line 121 of file conn.c.

{
       metaconn_t    *mc1 = ( metaconn_t * )c1;
       metaconn_t    *mc2 = ( metaconn_t * )c2;

       /* Cannot have more than one shared session with same DN */
       if ( mc1->mc_conn == mc2->mc_conn &&
              dn_match( &mc1->mc_local_ndn, &mc2->mc_local_ndn ) )
       {
              return -1;
       }
              
       return 0;
}

Here is the caller graph for this function:

int meta_back_controls_add ( Operation op,
SlapReply rs,
metaconn_t mc,
int  candidate,
LDAPControl ***  pctrls 
)

Definition at line 1627 of file bind.c.

{
       metainfo_t           *mi = (metainfo_t *)op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];

       LDAPControl          **ctrls = NULL;
       /* set to the maximum number of controls this backend can add */
       LDAPControl          c[ 2 ] = {{ 0 }};
       int                  n = 0, i, j1 = 0, j2 = 0;

       *pctrls = NULL;

       rs->sr_err = LDAP_SUCCESS;

       /* don't add controls if protocol is not LDAPv3 */
       switch ( mt->mt_version ) {
       case LDAP_VERSION3:
              break;

       case 0:
              if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
                     break;
              }
              /* fall thru */

       default:
              goto done;
       }

       /* put controls that go __before__ existing ones here */

       /* proxyAuthz for identity assertion */
       switch ( mi->mi_ldap_extra->proxy_authz_ctrl( op, rs, &msc->msc_bound_ndn,
              mt->mt_version, &mt->mt_idassert, &c[ j1 ] ) )
       {
       case SLAP_CB_CONTINUE:
              break;

       case LDAP_SUCCESS:
              j1++;
              break;

       default:
              goto done;
       }

       /* put controls that go __after__ existing ones here */

#ifdef SLAP_CONTROL_X_SESSION_TRACKING
       /* session tracking */
       if ( META_BACK_TGT_ST_REQUEST( mt ) ) {
              switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j1 + j2 ] ) ) {
              case SLAP_CB_CONTINUE:
                     break;

              case LDAP_SUCCESS:
                     j2++;
                     break;

              default:
                     goto done;
              }
       }
#endif /* SLAP_CONTROL_X_SESSION_TRACKING */

       if ( rs->sr_err == SLAP_CB_CONTINUE ) {
              rs->sr_err = LDAP_SUCCESS;
       }

       /* if nothing to do, just bail out */
       if ( j1 == 0 && j2 == 0 ) {
              goto done;
       }

       assert( j1 + j2 <= (int) (sizeof( c )/sizeof( c[0] )) );

       if ( op->o_ctrls ) {
              for ( n = 0; op->o_ctrls[ n ]; n++ )
                     /* just count ctrls */ ;
       }

       ctrls = op->o_tmpalloc( (n + j1 + j2 + 1) * sizeof( LDAPControl * ) + ( j1 + j2 ) * sizeof( LDAPControl ),
                     op->o_tmpmemctx );
       if ( j1 ) {
              ctrls[ 0 ] = (LDAPControl *)&ctrls[ n + j1 + j2 + 1 ];
              *ctrls[ 0 ] = c[ 0 ];
              for ( i = 1; i < j1; i++ ) {
                     ctrls[ i ] = &ctrls[ 0 ][ i ];
                     *ctrls[ i ] = c[ i ];
              }
       }

       i = 0;
       if ( op->o_ctrls ) {
              for ( i = 0; op->o_ctrls[ i ]; i++ ) {
                     ctrls[ i + j1 ] = op->o_ctrls[ i ];
              }
       }

       n += j1;
       if ( j2 ) {
              ctrls[ n ] = (LDAPControl *)&ctrls[ n + j2 + 1 ] + j1;
              *ctrls[ n ] = c[ j1 ];
              for ( i = 1; i < j2; i++ ) {
                     ctrls[ n + i ] = &ctrls[ n ][ i ];
                     *ctrls[ n + i ] = c[ i ];
              }
       }

       ctrls[ n + j2 ] = NULL;

done:;
       if ( ctrls == NULL ) {
              ctrls = op->o_ctrls;
       }

       *pctrls = ctrls;
       
       return rs->sr_err;
}

Here is the caller graph for this function:

int meta_back_dobind ( Operation op,
SlapReply rs,
metaconn_t mc,
ldap_back_send_t  sendok 
)

Definition at line 674 of file bind.c.

{
       metainfo_t           *mi = ( metainfo_t * )op->o_bd->be_private;

       int                  bound = 0,
                            i,
                            isroot = 0;

       SlapReply            *candidates;

       if ( be_isroot( op ) ) {
              isroot = 1;
       }

       if ( LogTest( LDAP_DEBUG_TRACE ) ) {
              char buf[STRLENOF("4294967295U") + 1] = { 0 };
              mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

              Debug( LDAP_DEBUG_TRACE,
                     "%s meta_back_dobind: conn=%s%s\n",
                     op->o_log_prefix, buf,
                     isroot ? " (isroot)" : "" );
       }

       /*
        * all the targets are bound as pseudoroot
        */
       if ( mc->mc_authz_target == META_BOUND_ALL ) {
              bound = 1;
              goto done;
       }

       candidates = meta_back_candidates_get( op );

       for ( i = 0; i < mi->mi_ntargets; i++ ) {
              metatarget_t         *mt = mi->mi_targets[ i ];
              metasingleconn_t     *msc = &mc->mc_conns[ i ];
              int                  rc;

              /*
               * Not a candidate
               */
              if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
                     continue;
              }

              assert( msc->msc_ld != NULL );

              /*
               * If the target is already bound it is skipped
               */

retry_binding:;
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
              if ( LDAP_BACK_CONN_ISBOUND( msc )
                     || ( LDAP_BACK_CONN_ISANON( msc )
                            && mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) )
              {
                     ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                     ++bound;
                     continue;

              } else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) )
              {
                     ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                     ldap_pvt_thread_yield();
                     goto retry_binding;

              }

              LDAP_BACK_CONN_BINDING_SET( msc );
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

              rc = meta_back_single_dobind( op, rs, &mc, i,
                     LDAP_BACK_DONTSEND, mt->mt_nretries, 1 );
              /*
               * NOTE: meta_back_single_dobind() already retries;
               * in case of failure, it resets mc...
               */
              if ( rc != LDAP_SUCCESS ) {
                     char          buf[ SLAP_TEXT_BUFLEN ];

                     if ( mc == NULL ) {
                            /* meta_back_single_dobind() already sent 
                             * response and released connection */
                            goto send_err;
                     }


                     if ( rc == LDAP_UNAVAILABLE ) {
                            /* FIXME: meta_back_retry() already re-calls
                             * meta_back_single_dobind() */
                            if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
                                   goto retry_ok;
                            }

                            if ( mc != NULL ) {
                                   ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                                   LDAP_BACK_CONN_BINDING_CLEAR( msc );
                                   meta_back_release_conn_lock( mi, mc, 0 );
                                   ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                            }

                            return 0;
                     }

                     ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                     LDAP_BACK_CONN_BINDING_CLEAR( msc );
                     ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

                     snprintf( buf, sizeof( buf ),
                            "meta_back_dobind[%d]: (%s) err=%d (%s).",
                            i, isroot ? op->o_bd->be_rootdn.bv_val : "anonymous",
                            rc, ldap_err2string( rc ) );
                     Debug( LDAP_DEBUG_ANY,
                            "%s %s\n",
                            op->o_log_prefix, buf, 0 );

                     /*
                      * null cred bind should always succeed
                      * as anonymous, so a failure means
                      * the target is no longer candidate possibly
                      * due to technical reasons (remote host down?)
                      * so better clear the handle
                      */
                     /* leave the target candidate, but record the error for later use */
                     candidates[ i ].sr_err = rc;
                     if ( META_BACK_ONERR_STOP( mi ) ) {
                            bound = 0;
                            goto done;
                     }

                     continue;
              } /* else */

retry_ok:;
              Debug( LDAP_DEBUG_TRACE,
                     "%s meta_back_dobind[%d]: "
                     "(%s)\n",
                     op->o_log_prefix, i,
                     isroot ? op->o_bd->be_rootdn.bv_val : "anonymous" );

              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
              LDAP_BACK_CONN_BINDING_CLEAR( msc );
              if ( isroot ) {
                     LDAP_BACK_CONN_ISBOUND_SET( msc );
              } else {
                     LDAP_BACK_CONN_ISANON_SET( msc );
              }
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
              ++bound;
       }

done:;
       if ( LogTest( LDAP_DEBUG_TRACE ) ) {
              char buf[STRLENOF("4294967295U") + 1] = { 0 };
              mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

              Debug( LDAP_DEBUG_TRACE,
                     "%s meta_back_dobind: conn=%s bound=%d\n",
                     op->o_log_prefix, buf, bound );
       }

       if ( bound == 0 ) {
              meta_back_release_conn( mi, mc );

send_err:;
              if ( sendok & LDAP_BACK_SENDERR ) {
                     if ( rs->sr_err == LDAP_SUCCESS ) {
                            rs->sr_err = LDAP_BUSY;
                     }
                     send_ldap_result( op, rs );
              }

              return 0;
       }

       return ( bound > 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

metaconn_t* meta_back_getconn ( Operation op,
SlapReply rs,
int candidate,
ldap_back_send_t  sendok 
)

Definition at line 1063 of file conn.c.

{
       metainfo_t    *mi = ( metainfo_t * )op->o_bd->be_private;
       metaconn_t    *mc = NULL,
                     mc_curr = {{ 0 }};
       int           cached = META_TARGET_NONE,
                     i = META_TARGET_NONE,
                     err = LDAP_SUCCESS,
                     new_conn = 0,
                     ncandidates = 0;


       meta_op_type  op_type = META_OP_REQUIRE_SINGLE;
       enum          {
              META_DNTYPE_ENTRY,
              META_DNTYPE_PARENT,
              META_DNTYPE_NEWPARENT
       }             dn_type = META_DNTYPE_ENTRY;
       struct berval ndn = op->o_req_ndn,
                     pndn;

       SlapReply     *candidates = meta_back_candidates_get( op );

       /* Internal searches are privileged and shared. So is root. */
       if ( ( !BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ALWAYS( mi ) )
              || ( BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ANON( mi ) )
              || op->o_do_not_cache || be_isroot( op ) )
       {
              LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
              mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
              LDAP_BACK_PCONN_ROOTDN_SET( &mc_curr, op );

       } else if ( BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_NOANON( mi ) )
       {
              LDAP_BACK_CONN_ISANON_SET( &mc_curr );
              BER_BVSTR( &mc_curr.mc_local_ndn, "" );
              LDAP_BACK_PCONN_ANON_SET( &mc_curr, op );

       } else {
              mc_curr.mc_local_ndn = op->o_ndn;

              /* Explicit binds must not be shared */
              if ( !BER_BVISEMPTY( &op->o_ndn )
                     || op->o_tag == LDAP_REQ_BIND
                     || SLAP_IS_AUTHZ_BACKEND( op ) )
              {
                     mc_curr.mc_conn = op->o_conn;
       
              } else {
                     LDAP_BACK_CONN_ISANON_SET( &mc_curr );
                     LDAP_BACK_PCONN_ANON_SET( &mc_curr, op );
              }
       }

       /* Explicit Bind requests always get their own conn */
       if ( sendok & LDAP_BACK_BINDING ) {
              mc_curr.mc_conn = op->o_conn;

       } else {
              /* Searches for a metaconn in the avl tree */
retry_lock:;
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
              if ( LDAP_BACK_PCONN_ISPRIV( &mc_curr ) ) {
                     /* lookup a conn that's not binding */
                     LDAP_TAILQ_FOREACH( mc,
                            &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv,
                            mc_q )
                     {
                            if ( !LDAP_BACK_CONN_BINDING( mc ) && mc->mc_refcnt == 0 ) {
                                   break;
                            }
                     }

                     if ( mc != NULL ) {
                            /* move to tail of queue */
                            if ( mc != LDAP_TAILQ_LAST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
                                   metaconn_t, mc_q ) )
                            {
                                   LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
                                          mc, mc_q );
                                   LDAP_TAILQ_ENTRY_INIT( mc, mc_q );
                                   LDAP_TAILQ_INSERT_TAIL( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
                                          mc, mc_q );
                            }

                     } else if ( !LDAP_BACK_USE_TEMPORARIES( mi )
                            && mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_num == mi->mi_conn_priv_max )
                     {
                            mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv );
                     }
                     

              } else {
                     mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, 
                            (caddr_t)&mc_curr, meta_back_conndn_cmp );
              }

              if ( mc ) {
                     /* catch taint errors */
                     assert( !LDAP_BACK_CONN_TAINTED( mc ) );

                     /* Don't reuse connections while they're still binding
                      * NOTE: only makes sense for binds */
                     if ( LDAP_BACK_CONN_BINDING( mc ) ) {
                            if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
                                   ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

                                   ldap_pvt_thread_yield();
                                   goto retry_lock;
                            }

                            /* release conn, and create a temporary */
                            mc = NULL;

                     } else {
                            if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
                                   || ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
                            {
#if META_BACK_PRINT_CONNTREE > 0
                                   meta_back_print_conntree( mi,
                                          ">>> meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */

                                   /* don't let anyone else use this expired connection */
                                   if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
                                          if ( mc->mc_q.tqe_prev != NULL ) {
                                                 assert( LDAP_BACK_CONN_CACHED( mc ) );
                                                 assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
                                                 LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
                                                        mc, mc_q );
                                                 mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
                                                 LDAP_TAILQ_ENTRY_INIT( mc, mc_q );

                                          } else {
                                                 assert( !LDAP_BACK_CONN_CACHED( mc ) );
                                          }

                                   } else {
                                          (void)avl_delete( &mi->mi_conninfo.lai_tree,
                                                 (caddr_t)mc, meta_back_conndnmc_cmp );
                                   }

#if META_BACK_PRINT_CONNTREE > 0
                                   meta_back_print_conntree( mi,
                                          "<<< meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */
                                   LDAP_BACK_CONN_TAINTED_SET( mc );
                                   LDAP_BACK_CONN_CACHED_CLEAR( mc );

                                   if ( LogTest( LDAP_DEBUG_TRACE ) ) {
                                          char buf[STRLENOF("4294967295U") + 1] = { 0 };
                                          mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

                                          Debug( LDAP_DEBUG_TRACE,
                                                 "%s meta_back_getconn: mc=%p conn=%s expired (tainted).\n",
                                                 op->o_log_prefix, (void *)mc, buf );
                                   }
                            }

                            mc->mc_refcnt++;
                     }
              }
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
       }

       switch ( op->o_tag ) {
       case LDAP_REQ_ADD:
              /* if we go to selection, the entry must not exist,
               * and we must be able to resolve the parent */
              dn_type = META_DNTYPE_PARENT;
              dnParent( &ndn, &pndn );
              break;

       case LDAP_REQ_MODRDN:
              /* if nnewSuperior is not NULL, it must resolve
               * to the same candidate as the req_ndn */
              if ( op->orr_nnewSup ) {
                     dn_type = META_DNTYPE_NEWPARENT;
              }
              break;

       case LDAP_REQ_BIND:
              /* if bound as rootdn, the backend must bind to all targets
               * with the administrative identity
               * (unless pseoudoroot-bind-defer is TRUE) */
              if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op ) ) {
                     op_type = META_OP_REQUIRE_ALL;
              }
              break;

       case LDAP_REQ_COMPARE:
       case LDAP_REQ_DELETE:
       case LDAP_REQ_MODIFY:
              /* just a unique candidate */
              break;

       case LDAP_REQ_SEARCH:
              /* allow multiple candidates for the searchBase */
              op_type = META_OP_ALLOW_MULTIPLE;
              break;

       default:
              /* right now, just break (exop?) */
              break;
       }

       /*
        * require all connections ...
        */
       if ( op_type == META_OP_REQUIRE_ALL ) {

              /* Looks like we didn't get a bind. Open a new session... */
              if ( mc == NULL ) {
                     assert( new_conn == 0 );
                     mc = metaconn_alloc( op );
                     mc->mc_conn = mc_curr.mc_conn;
                     ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                     new_conn = 1;
                     if ( sendok & LDAP_BACK_BINDING ) {
                            LDAP_BACK_CONN_BINDING_SET( mc );
                     }
                     if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
                            LDAP_BACK_CONN_ISPRIV_SET( mc );

                     } else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
                            LDAP_BACK_CONN_ISANON_SET( mc );
                     }

              } else if ( 0 ) {
                     /* TODO: if any of the connections is binding,
                      * release mc and create a new one */
              }

              for ( i = 0; i < mi->mi_ntargets; i++ ) {
                     /*
                      * The target is activated; if needed, it is
                      * also init'd
                      */
                     candidates[ i ].sr_err = meta_back_init_one_conn( op,
                            rs, mc, i, LDAP_BACK_CONN_ISPRIV( &mc_curr ),
                            LDAP_BACK_DONTSEND, !new_conn );
                     if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
                            if ( new_conn && ( sendok & LDAP_BACK_BINDING ) ) {
                                   LDAP_BACK_CONN_BINDING_SET( &mc->mc_conns[ i ] );
                            }
                            META_CANDIDATE_SET( &candidates[ i ] );
                            ncandidates++;
       
                     } else {
                            
                            /*
                             * FIXME: in case one target cannot
                             * be init'd, should the other ones
                             * be tried?
                             */
                            META_CANDIDATE_RESET( &candidates[ i ] );
                            err = candidates[ i ].sr_err;
                            continue;
                     }
              }

              if ( ncandidates == 0 ) {
                     if ( new_conn ) {
                            mc->mc_refcnt = 0;
                            meta_back_conn_free( mc );

                     } else {
                            meta_back_release_conn( mi, mc );
                     }

                     rs->sr_err = LDAP_NO_SUCH_OBJECT;
                     rs->sr_text = "Unable to select valid candidates";

                     if ( sendok & LDAP_BACK_SENDERR ) {
                            if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                                   rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
                            }
                            send_ldap_result( op, rs );
                            rs->sr_matched = NULL;
                     }

                     return NULL;
              }

              goto done;
       }
       
       /*
        * looks in cache, if any
        */
       if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
              cached = i = meta_dncache_get_target( &mi->mi_cache, &op->o_req_ndn );
       }

       if ( op_type == META_OP_REQUIRE_SINGLE ) {
              metatarget_t         *mt = NULL;
              metasingleconn_t     *msc = NULL;

              int                  j;

              for ( j = 0; j < mi->mi_ntargets; j++ ) {
                     META_CANDIDATE_RESET( &candidates[ j ] );
              }

              /*
               * tries to get a unique candidate
               * (takes care of default target)
               */
              if ( i == META_TARGET_NONE ) {
                     i = meta_back_get_candidate( op, rs, &ndn );

                     if ( rs->sr_err == LDAP_NO_SUCH_OBJECT && dn_type == META_DNTYPE_PARENT ) {
                            i = meta_back_get_candidate( op, rs, &pndn );
                     }
       
                     if ( i < 0 || rs->sr_err != LDAP_SUCCESS ) {
                            if ( mc != NULL ) {
                                   meta_back_release_conn( mi, mc );
                            }

                            if ( sendok & LDAP_BACK_SENDERR ) {
                                   if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                                          rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
                                   }
                                   send_ldap_result( op, rs );
                                   rs->sr_matched = NULL;
                            }
                     
                            return NULL;
                     }
              }

              if ( dn_type == META_DNTYPE_NEWPARENT && meta_back_get_candidate( op, rs, op->orr_nnewSup ) != i )
              {
                     if ( mc != NULL ) {
                            meta_back_release_conn( mi, mc );
                     }

                     rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                     rs->sr_text = "Cross-target rename not supported";
                     if ( sendok & LDAP_BACK_SENDERR ) {
                            send_ldap_result( op, rs );
                     }

                     return NULL;
              }

              Debug( LDAP_DEBUG_TRACE,
       "==>meta_back_getconn: got target=%d for ndn=\"%s\" from cache\n",
                            i, op->o_req_ndn.bv_val, 0 );

              if ( mc == NULL ) {
                     /* Retries searching for a metaconn in the avl tree
                      * the reason is that the connection might have been
                      * created by meta_back_get_candidate() */
                     if ( !( sendok & LDAP_BACK_BINDING ) ) {
retry_lock2:;
                            ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                            mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, 
                                   (caddr_t)&mc_curr, meta_back_conndn_cmp );
                            if ( mc != NULL ) {
                                   /* catch taint errors */
                                   assert( !LDAP_BACK_CONN_TAINTED( mc ) );

                                   /* Don't reuse connections while they're still binding */
                                   if ( META_BACK_CONN_CREATING( &mc->mc_conns[ i ] )
                                          || LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) )
                                   {
                                          if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
                                                 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                                                 ldap_pvt_thread_yield();
                                                 goto retry_lock2;
                                          }

                                          mc = NULL;

                                   } else {
                                          mc->mc_refcnt++;
                                   }
                            }
                            ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                     }

                     /* Looks like we didn't get a bind. Open a new session... */
                     if ( mc == NULL ) {
                            assert( new_conn == 0 );
                            mc = metaconn_alloc( op );
                            mc->mc_conn = mc_curr.mc_conn;
                            ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                            new_conn = 1;
                            if ( sendok & LDAP_BACK_BINDING ) {
                                   LDAP_BACK_CONN_BINDING_SET( mc );
                            }
                            if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
                                   LDAP_BACK_CONN_ISPRIV_SET( mc );

                            } else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
                                   LDAP_BACK_CONN_ISANON_SET( mc );
                            }
                     }
              }

              /*
               * Clear all other candidates
               */
              ( void )meta_clear_unused_candidates( op, i );

              mt = mi->mi_targets[ i ];
              msc = &mc->mc_conns[ i ];

              /*
               * The target is activated; if needed, it is
               * also init'd. In case of error, meta_back_init_one_conn
               * sends the appropriate result.
               */
              err = meta_back_init_one_conn( op, rs, mc, i,
                     LDAP_BACK_CONN_ISPRIV( &mc_curr ), sendok, !new_conn );
              if ( err != LDAP_SUCCESS ) {
                     /*
                      * FIXME: in case one target cannot
                      * be init'd, should the other ones
                      * be tried?
                      */
                     META_CANDIDATE_RESET( &candidates[ i ] );
                     if ( new_conn ) {
                            mc->mc_refcnt = 0;
                            meta_back_conn_free( mc );

                     } else {
                            meta_back_release_conn( mi, mc );
                     }
                     return NULL;
              }

              if ( new_conn && ( sendok & LDAP_BACK_BINDING ) ) {
                     LDAP_BACK_CONN_BINDING_SET( &mc->mc_conns[ i ] );
              }

              candidates[ i ].sr_err = LDAP_SUCCESS;
              META_CANDIDATE_SET( &candidates[ i ] );
              ncandidates++;

              if ( candidate ) {
                     *candidate = i;
              }

       /*
        * if no unique candidate ...
        */
       } else {

              /* Looks like we didn't get a bind. Open a new session... */
              if ( mc == NULL ) {
                     assert( new_conn == 0 );
                     mc = metaconn_alloc( op );
                     mc->mc_conn = mc_curr.mc_conn;
                     ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                     new_conn = 1;
                     if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
                            LDAP_BACK_CONN_ISPRIV_SET( mc );

                     } else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
                            LDAP_BACK_CONN_ISANON_SET( mc );
                     }
              }

              for ( i = 0; i < mi->mi_ntargets; i++ ) {
                     metatarget_t         *mt = mi->mi_targets[ i ];

                     META_CANDIDATE_RESET( &candidates[ i ] );

                     if ( i == cached 
                            || meta_back_is_candidate( mt, &op->o_req_ndn,
                                   op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_SUBTREE ) )
                     {

                            /*
                             * The target is activated; if needed, it is
                             * also init'd
                             */
                            int lerr = meta_back_init_one_conn( op, rs, mc, i,
                                   LDAP_BACK_CONN_ISPRIV( &mc_curr ),
                                   LDAP_BACK_DONTSEND, !new_conn );
                            candidates[ i ].sr_err = lerr;
                            if ( lerr == LDAP_SUCCESS ) {
                                   META_CANDIDATE_SET( &candidates[ i ] );
                                   ncandidates++;

                                   Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d]\n",
                                          op->o_log_prefix, i, 0 );

                            } else if ( lerr == LDAP_UNAVAILABLE && !META_BACK_ONERR_STOP( mi ) ) {
                                   META_CANDIDATE_SET( &candidates[ i ] );

                                   Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] %s\n",
                                          op->o_log_prefix, i,
                                          mt->mt_isquarantined != LDAP_BACK_FQ_NO ? "quarantined" : "unavailable" );

                            } else {
                            
                                   /*
                                    * FIXME: in case one target cannot
                                    * be init'd, should the other ones
                                    * be tried?
                                    */
                                   if ( new_conn ) {
                                          ( void )meta_clear_one_candidate( op, mc, i );
                                   }
                                   /* leave the target candidate, but record the error for later use */
                                   err = lerr;

                                   if ( lerr == LDAP_UNAVAILABLE && mt->mt_isquarantined != LDAP_BACK_FQ_NO ) {
                                          Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] quarantined err=%d\n",
                                                 op->o_log_prefix, i, lerr );

                                   } else {
                                          Debug( LDAP_DEBUG_ANY, "%s: meta_back_getconn[%d] failed err=%d\n",
                                                 op->o_log_prefix, i, lerr );
                                   }

                                   if ( META_BACK_ONERR_STOP( mi ) ) {
                                          if ( sendok & LDAP_BACK_SENDERR ) {
                                                 send_ldap_result( op, rs );
                                          }
                                          if ( new_conn ) {
                                                 mc->mc_refcnt = 0;
                                                 meta_back_conn_free( mc );

                                          } else {
                                                 meta_back_release_conn( mi, mc );
                                          }

                                          return NULL;
                                   }

                                   continue;
                            }

                     } else {
                            if ( new_conn ) {
                                   ( void )meta_clear_one_candidate( op, mc, i );
                            }
                     }
              }

              if ( ncandidates == 0 ) {
                     if ( new_conn ) {
                            mc->mc_refcnt = 0;
                            meta_back_conn_free( mc );

                     } else {
                            meta_back_release_conn( mi, mc );
                     }

                     if ( rs->sr_err == LDAP_SUCCESS ) {
                            rs->sr_err = LDAP_NO_SUCH_OBJECT;
                            rs->sr_text = "Unable to select valid candidates";
                     }

                     if ( sendok & LDAP_BACK_SENDERR ) {
                            if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                                   rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
                            }
                            send_ldap_result( op, rs );
                            rs->sr_matched = NULL;
                     }

                     return NULL;
              }
       }

done:;
       /* clear out meta_back_init_one_conn non-fatal errors */
       rs->sr_err = LDAP_SUCCESS;
       rs->sr_text = NULL;

       /* touch the timestamp */
       if ( mi->mi_idle_timeout != 0 ) {
              mc->mc_time = op->o_time;
       }

       if ( new_conn ) {
              if ( mi->mi_conn_ttl ) {
                     mc->mc_create_time = op->o_time;
              }

              /*
               * Inserts the newly created metaconn in the avl tree
               */
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
#if META_BACK_PRINT_CONNTREE > 0
              meta_back_print_conntree( mi, ">>> meta_back_getconn" );
#endif /* META_BACK_PRINT_CONNTREE */

              err = 0;
              if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
                     if ( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num < mi->mi_conn_priv_max ) {
                            LDAP_TAILQ_INSERT_TAIL( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv, mc, mc_q );
                            mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num++;
                            LDAP_BACK_CONN_CACHED_SET( mc );

                     } else {
                            LDAP_BACK_CONN_TAINTED_SET( mc );
                     }
                     rs->sr_err = 0;

              } else if ( !( sendok & LDAP_BACK_BINDING ) ) {
                     err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
                                   meta_back_conndn_cmp, meta_back_conndn_dup );
                     LDAP_BACK_CONN_CACHED_SET( mc );
              }

#if META_BACK_PRINT_CONNTREE > 0
              meta_back_print_conntree( mi, "<<< meta_back_getconn" );
#endif /* META_BACK_PRINT_CONNTREE */
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

              if ( !LDAP_BACK_PCONN_ISPRIV( mc ) ) {
                     /*
                      * Err could be -1 in case a duplicate metaconn is inserted
                      */
                     switch ( err ) {
                     case 0:
                            break;

                     case -1:
                            LDAP_BACK_CONN_CACHED_CLEAR( mc );
                            /* duplicate: free and try to get the newly created one */
                            if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
                                   mc->mc_refcnt = 0;   
                                   meta_back_conn_free( mc );
       
                                   new_conn = 0;
                                   goto retry_lock;
                            }

                            LDAP_BACK_CONN_TAINTED_SET( mc );
                            break;

                     default:
                            LDAP_BACK_CONN_CACHED_CLEAR( mc );
                            if ( LogTest( LDAP_DEBUG_ANY ) ) {
                                   char buf[STRLENOF("4294967295U") + 1] = { 0 };
                                   mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

                                   Debug( LDAP_DEBUG_ANY,
                                          "%s meta_back_getconn: candidates=%d conn=%s insert failed\n",
                                          op->o_log_prefix, ncandidates, buf );
                            }
       
                            mc->mc_refcnt = 0;   
                            meta_back_conn_free( mc );

                            rs->sr_err = LDAP_OTHER;
                            rs->sr_text = "Proxy bind collision";
                            if ( sendok & LDAP_BACK_SENDERR ) {
                                   send_ldap_result( op, rs );
                            }
                            return NULL;
                     }
              }

              if ( LogTest( LDAP_DEBUG_TRACE ) ) {
                     char buf[STRLENOF("4294967295U") + 1] = { 0 };
                     mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

                     Debug( LDAP_DEBUG_TRACE,
                            "%s meta_back_getconn: candidates=%d conn=%s inserted\n",
                            op->o_log_prefix, ncandidates, buf );
              }

       } else {
              if ( LogTest( LDAP_DEBUG_TRACE ) ) {
                     char buf[STRLENOF("4294967295U") + 1] = { 0 };
                     mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

                     Debug( LDAP_DEBUG_TRACE,
                            "%s meta_back_getconn: candidates=%d conn=%s fetched\n",
                            op->o_log_prefix, ncandidates, buf );
              }
       }

       return mc;
}

Here is the caller graph for this function:

int meta_back_init_one_conn ( Operation op,
SlapReply rs,
metaconn_t mc,
int  candidate,
int  ispriv,
ldap_back_send_t  sendok,
int  dolock 
)

Definition at line 266 of file conn.c.

{
       metainfo_t           *mi = ( metainfo_t * )op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];
       int                  version;
       dncookie             dc;
       int                  isauthz = ( candidate == mc->mc_authz_target );
       int                  do_return = 0;
#ifdef HAVE_TLS
       int                  is_ldaps = 0;
       int                  do_start_tls = 0;
#endif /* HAVE_TLS */

       /* if the server is quarantined, and
        * - the current interval did not expire yet, or
        * - no more retries should occur,
        * don't return the connection */
       if ( mt->mt_isquarantined ) {
              slap_retry_info_t    *ri = &mt->mt_quarantine;
              int                  dont_retry = 0;

              if ( mt->mt_quarantine.ri_interval ) {
                     ldap_pvt_thread_mutex_lock( &mt->mt_quarantine_mutex );
                     dont_retry = ( mt->mt_isquarantined > LDAP_BACK_FQ_NO );
                     if ( dont_retry ) {
                            dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL
                                   || slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] );
                            if ( !dont_retry ) {
                                   if ( LogTest( LDAP_DEBUG_ANY ) ) {
                                          char   buf[ SLAP_TEXT_BUFLEN ];

                                          snprintf( buf, sizeof( buf ),
                                                 "meta_back_init_one_conn[%d]: quarantine "
                                                 "retry block #%d try #%d",
                                                 candidate, ri->ri_idx, ri->ri_count );
                                          Debug( LDAP_DEBUG_ANY, "%s %s.\n",
                                                 op->o_log_prefix, buf, 0 );
                                   }

                                   mt->mt_isquarantined = LDAP_BACK_FQ_RETRYING;
                            }

                     }
                     ldap_pvt_thread_mutex_unlock( &mt->mt_quarantine_mutex );
              }

              if ( dont_retry ) {
                     rs->sr_err = LDAP_UNAVAILABLE;
                     if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
                            rs->sr_text = "Target is quarantined";
                            send_ldap_result( op, rs );
                     }
                     return rs->sr_err;
              }
       }

retry_lock:;
       if ( dolock ) {
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
       }

       /*
        * Already init'ed
        */
       if ( LDAP_BACK_CONN_ISBOUND( msc )
              || LDAP_BACK_CONN_ISANON( msc ) )
       {
              assert( msc->msc_ld != NULL );
              rs->sr_err = LDAP_SUCCESS;
              do_return = 1;

       } else if ( META_BACK_CONN_CREATING( msc )
              || LDAP_BACK_CONN_BINDING( msc ) )
       {
              if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
                     if ( dolock ) {
                            ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                     }

                     ldap_pvt_thread_yield();
                     goto retry_lock;
              }

              /* sounds more appropriate */
              rs->sr_err = LDAP_BUSY;
              rs->sr_text = "No connections to target are available";
              do_return = 1;

       } else if ( META_BACK_CONN_INITED( msc ) ) {
              assert( msc->msc_ld != NULL );
              rs->sr_err = LDAP_SUCCESS;
              do_return = 1;

       } else {
              /*
               * creating...
               */
              META_BACK_CONN_CREATING_SET( msc );
       }

       if ( dolock ) {
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
       }

       if ( do_return ) {
              if ( rs->sr_err != LDAP_SUCCESS
                     && op->o_conn
                     && ( sendok & LDAP_BACK_SENDERR ) )
              {
                     send_ldap_result( op, rs );
              }

              return rs->sr_err;
       }

       assert( msc->msc_ld == NULL );
       
       /*
        * Attempts to initialize the connection to the target ds
        */
       ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
       rs->sr_err = ldap_initialize( &msc->msc_ld, mt->mt_uri );
#ifdef HAVE_TLS
       is_ldaps = ldap_is_ldaps_url( mt->mt_uri );
#endif /* HAVE_TLS */
       ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
       if ( rs->sr_err != LDAP_SUCCESS ) {
              goto error_return;
       }

       /*
        * Set LDAP version. This will always succeed: If the client
        * bound with a particular version, then so can we.
        */
       if ( mt->mt_version != 0 ) {
              version = mt->mt_version;

       } else if ( op->o_conn->c_protocol != 0 ) {
              version = op->o_conn->c_protocol;

       } else {
              version = LDAP_VERSION3;
       }
       ldap_set_option( msc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &version );
       ldap_set_urllist_proc( msc->msc_ld, mt->mt_urllist_f, mt->mt_urllist_p );

       /* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */
       ldap_set_option( msc->msc_ld, LDAP_OPT_REFERRALS,
              META_BACK_TGT_CHASE_REFERRALS( mt ) ? LDAP_OPT_ON : LDAP_OPT_OFF );

#ifdef HAVE_TLS
       if ( !is_ldaps ) {
              slap_bindconf *sb = NULL;

              if ( ispriv ) {
                     sb = &mt->mt_idassert.si_bc;
              } else {
                     sb = &mt->mt_tls;
              }

              if ( sb->sb_tls_do_init ) {
                     bindconf_tls_set( sb, msc->msc_ld );
              } else if ( sb->sb_tls_ctx ) {
                     ldap_set_option( msc->msc_ld, LDAP_OPT_X_TLS_CTX, sb->sb_tls_ctx );
              }

              if ( sb == &mt->mt_idassert.si_bc && sb->sb_tls_ctx ) {
                     do_start_tls = 1;

              } else if ( META_BACK_TGT_USE_TLS( mt )
                     || ( op->o_conn->c_is_tls && META_BACK_TGT_PROPAGATE_TLS( mt ) ) )
              {
                     do_start_tls = 1;
              }
       }

       /* start TLS ("tls [try-]{start|propagate}" statement) */
       if ( do_start_tls ) {
#ifdef SLAP_STARTTLS_ASYNCHRONOUS
              /*
               * use asynchronous StartTLS; in case, chase referral
               * FIXME: OpenLDAP does not return referral on StartTLS yet
               */
              int           msgid;

              rs->sr_err = ldap_start_tls( msc->msc_ld, NULL, NULL, &msgid );
              if ( rs->sr_err == LDAP_SUCCESS ) {
                     LDAPMessage   *res = NULL;
                     int           rc, nretries = mt->mt_nretries;
                     struct timeval       tv;

                     LDAP_BACK_TV_SET( &tv );

retry:;
                     rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
                     switch ( rc ) {
                     case -1:
                            rs->sr_err = LDAP_OTHER;
                            break;

                     case 0:
                            if ( nretries != 0 ) {
                                   if ( nretries > 0 ) {
                                          nretries--;
                                   }
                                   LDAP_BACK_TV_SET( &tv );
                                   goto retry;
                            }
                            rs->sr_err = LDAP_OTHER;
                            break;

                     default:
                            /* only touch when activity actually took place... */
                            if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
                                   msc->msc_time = op->o_time;
                            }
                            break;
                     }

                     if ( rc == LDAP_RES_EXTENDED ) {
                            struct berval *data = NULL;

                            /* NOTE: right now, data is unused, so don't get it */
                            rs->sr_err = ldap_parse_extended_result( msc->msc_ld,
                                   res, NULL, NULL /* &data */ , 0 );
                            if ( rs->sr_err == LDAP_SUCCESS ) {
                                   int           err;

                                   /* FIXME: matched? referrals? response controls? */
                                   rs->sr_err = ldap_parse_result( msc->msc_ld,
                                          res, &err, NULL, NULL, NULL, NULL, 1 );
                                   res = NULL;

                                   if ( rs->sr_err == LDAP_SUCCESS ) {
                                          rs->sr_err = err;
                                   }
                                   rs->sr_err = slap_map_api2result( rs );
                                   
                                   /* FIXME: in case a referral 
                                    * is returned, should we try
                                    * using it instead of the 
                                    * configured URI? */
                                   if ( rs->sr_err == LDAP_SUCCESS ) {
                                          ldap_install_tls( msc->msc_ld );

                                   } else if ( rs->sr_err == LDAP_REFERRAL ) {
                                          /* FIXME: LDAP_OPERATIONS_ERROR? */
                                          rs->sr_err = LDAP_OTHER;
                                          rs->sr_text = "Unwilling to chase referral "
                                                 "returned by Start TLS exop";
                                   }

                                   if ( data ) {
                                          ber_bvfree( data );
                                   }
                            }

                     } else {
                            rs->sr_err = LDAP_OTHER;
                     }

                     if ( res != NULL ) {
                            ldap_msgfree( res );
                     }
              }
#else /* ! SLAP_STARTTLS_ASYNCHRONOUS */
              /*
               * use synchronous StartTLS
               */
              rs->sr_err = ldap_start_tls_s( msc->msc_ld, NULL, NULL );
#endif /* ! SLAP_STARTTLS_ASYNCHRONOUS */

              /* if StartTLS is requested, only attempt it if the URL
               * is not "ldaps://"; this may occur not only in case
               * of misconfiguration, but also when used in the chain 
               * overlay, where the "uri" can be parsed out of a referral */
              if ( rs->sr_err == LDAP_SERVER_DOWN
                     || ( rs->sr_err != LDAP_SUCCESS
                            && META_BACK_TGT_TLS_CRITICAL( mt ) ) )
              {

#ifdef DEBUG_205
                     Debug( LDAP_DEBUG_ANY,
                            "### %s meta_back_init_one_conn(TLS) "
                            "ldap_unbind_ext[%d] ld=%p\n",
                            op->o_log_prefix, candidate,
                            (void *)msc->msc_ld );
#endif /* DEBUG_205 */

                     /* need to trash a failed Start TLS */
                     meta_clear_one_candidate( op, mc, candidate );
                     goto error_return;
              }
       }
#endif /* HAVE_TLS */

       /*
        * Set the network timeout if set
        */
       if ( mt->mt_network_timeout != 0 ) {
              struct timeval       network_timeout;

              network_timeout.tv_usec = 0;
              network_timeout.tv_sec = mt->mt_network_timeout;

              ldap_set_option( msc->msc_ld, LDAP_OPT_NETWORK_TIMEOUT,
                            (void *)&network_timeout );
       }

       /*
        * If the connection DN is not null, an attempt to rewrite it is made
        */

       if ( ispriv ) {
              if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
                     ber_bvreplace( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN );
                     if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
                            if ( !BER_BVISNULL( &msc->msc_cred ) ) {
                                   memset( msc->msc_cred.bv_val, 0,
                                          msc->msc_cred.bv_len );
                            }
                            ber_bvreplace( &msc->msc_cred, &mt->mt_idassert_passwd );
                     }
                     LDAP_BACK_CONN_ISIDASSERT_SET( msc );

              } else {
                     ber_bvreplace( &msc->msc_bound_ndn, &slap_empty_bv );
              }

       } else {
              if ( !BER_BVISNULL( &msc->msc_cred ) ) {
                     memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
                     ber_memfree_x( msc->msc_cred.bv_val, NULL );
                     BER_BVZERO( &msc->msc_cred );
              }
              if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
                     ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
                     BER_BVZERO( &msc->msc_bound_ndn );
              }
              if ( !BER_BVISEMPTY( &op->o_ndn )
                     && SLAP_IS_AUTHZ_BACKEND( op )
                     && isauthz )
              {
                     dc.target = mt;
                     dc.conn = op->o_conn;
                     dc.rs = rs;
                     dc.ctx = "bindDN";
              
                     /*
                      * Rewrite the bind dn if needed
                      */
                     if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
                                          &msc->msc_bound_ndn ) )
                     {

#ifdef DEBUG_205
                            Debug( LDAP_DEBUG_ANY,
                                   "### %s meta_back_init_one_conn(rewrite) "
                                   "ldap_unbind_ext[%d] ld=%p\n",
                                   op->o_log_prefix, candidate,
                                   (void *)msc->msc_ld );
#endif /* DEBUG_205 */

                            /* need to trash a connection not fully established */
                            meta_clear_one_candidate( op, mc, candidate );
                            goto error_return;
                     }
                     
                     /* copy the DN if needed */
                     if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
                            ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
                     }

                     assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );

              } else {
                     ber_dupbv( &msc->msc_bound_ndn, (struct berval *)&slap_empty_bv );
              }
       }

       assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );

error_return:;
       if ( dolock ) {
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
       }
       META_BACK_CONN_CREATING_CLEAR( msc );
       if ( rs->sr_err == LDAP_SUCCESS ) {
              /*
               * Sets a cookie for the rewrite session
               */
              ( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
              META_BACK_CONN_INITED_SET( msc );
       }
       if ( dolock ) {
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
       }

       if ( rs->sr_err != LDAP_SUCCESS ) {
              rs->sr_err = slap_map_api2result( rs );
              if ( sendok & LDAP_BACK_SENDERR ) {
                     send_ldap_result( op, rs );
              }
       }

       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_is_candidate ( metatarget_t mt,
struct berval ndn,
int  scope 
)

Definition at line 94 of file candidates.c.

{
       struct berval rdn;
       int d = ndn->bv_len - mt->mt_nsuffix.bv_len;

       if ( d >= 0 ) {
              if ( !dnIsSuffix( ndn, &mt->mt_nsuffix ) ) {
                     return META_NOT_CANDIDATE;
              }

              /*
               * |  match  | exclude |
               * +---------+---------+-------------------+
               * |    T    |    T    | not candidate     |
               * |    F    |    T    | continue checking |
               * +---------+---------+-------------------+
               * |    T    |    F    | candidate         |
               * |    F    |    F    | not candidate     |
               * +---------+---------+-------------------+
               */
                     
              if ( mt->mt_subtree ) {
                     int match = ( meta_subtree_match( mt, ndn, scope ) != NULL );

                     if ( !mt->mt_subtree_exclude ) {
                            return match ? META_CANDIDATE : META_NOT_CANDIDATE;
                     }

                     if ( match /* && mt->mt_subtree_exclude */ ) {
                            return META_NOT_CANDIDATE;
                     }
              }

              switch ( mt->mt_scope ) {
              case LDAP_SCOPE_SUBTREE:
              default:
                     return META_CANDIDATE;

              case LDAP_SCOPE_SUBORDINATE:
                     if ( d > 0 ) {
                            return META_CANDIDATE;
                     }
                     break;

              /* nearly useless; not allowed by config */
              case LDAP_SCOPE_ONELEVEL:
                     if ( d > 0 ) {
                            rdn.bv_val = ndn->bv_val;
                            rdn.bv_len = (ber_len_t)d - STRLENOF( "," );
                            if ( dnIsOneLevelRDN( &rdn ) ) {
                                   return META_CANDIDATE;
                            }
                     }
                     break;

              /* nearly useless; not allowed by config */
              case LDAP_SCOPE_BASE:
                     if ( d == 0 ) {
                            return META_CANDIDATE;
                     }
                     break;
              }

       } else /* if ( d < 0 ) */ {
              if ( !dnIsSuffix( &mt->mt_nsuffix, ndn ) ) {
                     return META_NOT_CANDIDATE;
              }

              switch ( scope ) {
              case LDAP_SCOPE_SUBTREE:
              case LDAP_SCOPE_SUBORDINATE:
                     /*
                      * suffix longer than dn, but common part matches
                      */
                     return META_CANDIDATE;

              case LDAP_SCOPE_ONELEVEL:
                     rdn.bv_val = mt->mt_nsuffix.bv_val;
                     rdn.bv_len = (ber_len_t)(-d) - STRLENOF( "," );
                     if ( dnIsOneLevelRDN( &rdn ) ) {
                            return META_CANDIDATE;
                     }
                     break;
              }
       }

       return META_NOT_CANDIDATE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_op_result ( metaconn_t mc,
Operation op,
SlapReply rs,
int  candidate,
ber_int_t  msgid,
time_t  timeout,
ldap_back_send_t  sendok 
)

Definition at line 961 of file bind.c.

{
       metainfo_t    *mi = ( metainfo_t * )op->o_bd->be_private;

       const char    *save_text = rs->sr_text,
                     *save_matched = rs->sr_matched;
       BerVarray     save_ref = rs->sr_ref;
       LDAPControl   **save_ctrls = rs->sr_ctrls;
       void          *matched_ctx = NULL;

       char          *matched = NULL;
       char          *text = NULL;
       char          **refs = NULL;
       LDAPControl   **ctrls = NULL;

       assert( mc != NULL );

       rs->sr_text = NULL;
       rs->sr_matched = NULL;
       rs->sr_ref = NULL;
       rs->sr_ctrls = NULL;

       if ( candidate != META_TARGET_NONE ) {
              metatarget_t         *mt = mi->mi_targets[ candidate ];
              metasingleconn_t     *msc = &mc->mc_conns[ candidate ];

              if ( LDAP_ERR_OK( rs->sr_err ) ) {
                     int           rc;
                     struct timeval       tv;
                     LDAPMessage   *res = NULL;
                     time_t        stoptime = (time_t)(-1);
                     int           timeout_err = op->o_protocol >= LDAP_VERSION3 ?
                                          LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
                     const char    *timeout_text = "Operation timed out";

                     /* if timeout is not specified, compute and use
                      * the one specific to the ongoing operation */
                     if ( timeout == (time_t)(-1) ) {
                            slap_op_t     opidx = slap_req2op( op->o_tag );

                            if ( opidx == SLAP_OP_SEARCH ) {
                                   if ( op->ors_tlimit <= 0 ) {
                                          timeout = 0;

                                   } else {
                                          timeout = op->ors_tlimit;
                                          timeout_err = LDAP_TIMELIMIT_EXCEEDED;
                                          timeout_text = NULL;
                                   }

                            } else {
                                   timeout = mt->mt_timeout[ opidx ];
                            }
                     }

                     /* better than nothing :) */
                     if ( timeout == 0 ) {
                            if ( mi->mi_idle_timeout ) {
                                   timeout = mi->mi_idle_timeout;

                            } else if ( mi->mi_conn_ttl ) {
                                   timeout = mi->mi_conn_ttl;
                            }
                     }

                     if ( timeout ) {
                            stoptime = op->o_time + timeout;
                     }

                     LDAP_BACK_TV_SET( &tv );

retry:;
                     rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
                     switch ( rc ) {
                     case 0:
                            if ( timeout && slap_get_time() > stoptime ) {
                                   (void)meta_back_cancel( mc, op, rs, msgid, candidate, sendok );
                                   rs->sr_err = timeout_err;
                                   rs->sr_text = timeout_text;
                                   break;
                            }

                            LDAP_BACK_TV_SET( &tv );
                            ldap_pvt_thread_yield();
                            goto retry;

                     case -1:
                            ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE,
                                          &rs->sr_err );
                            break;


                     /* otherwise get the result; if it is not
                      * LDAP_SUCCESS, record it in the reply
                      * structure (this includes 
                      * LDAP_COMPARE_{TRUE|FALSE}) */
                     default:
                            /* only touch when activity actually took place... */
                            if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
                                   msc->msc_time = op->o_time;
                            }

                            rc = ldap_parse_result( msc->msc_ld, res, &rs->sr_err,
                                          &matched, &text, &refs, &ctrls, 1 );
                            res = NULL;
                            if ( rc == LDAP_SUCCESS ) {
                                   rs->sr_text = text;
                            } else {
                                   rs->sr_err = rc;
                            }
                            rs->sr_err = slap_map_api2result( rs );

                            /* RFC 4511: referrals can only appear
                             * if result code is LDAP_REFERRAL */
                            if ( refs != NULL
                                   && refs[ 0 ] != NULL
                                   && refs[ 0 ][ 0 ] != '\0' )
                            {
                                   if ( rs->sr_err != LDAP_REFERRAL ) {
                                          Debug( LDAP_DEBUG_ANY,
                                                 "%s meta_back_op_result[%d]: "
                                                 "got referrals with err=%d\n",
                                                 op->o_log_prefix,
                                                 candidate, rs->sr_err );

                                   } else {
                                          int    i;
       
                                          for ( i = 0; refs[ i ] != NULL; i++ )
                                                 /* count */ ;
                                          rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),
                                                 op->o_tmpmemctx );
                                          for ( i = 0; refs[ i ] != NULL; i++ ) {
                                                 ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );
                                          }
                                          BER_BVZERO( &rs->sr_ref[ i ] );
                                   }

                            } else if ( rs->sr_err == LDAP_REFERRAL ) {
                                   Debug( LDAP_DEBUG_ANY,
                                          "%s meta_back_op_result[%d]: "
                                          "got err=%d with null "
                                          "or empty referrals\n",
                                          op->o_log_prefix,
                                          candidate, rs->sr_err );

                                   rs->sr_err = LDAP_NO_SUCH_OBJECT;
                            }

                            if ( ctrls != NULL ) {
                                   rs->sr_ctrls = ctrls;
                            }
                     }

                     assert( res == NULL );
              }

              /* if the error in the reply structure is not
               * LDAP_SUCCESS, try to map it from client 
               * to server error */
              if ( !LDAP_ERR_OK( rs->sr_err ) ) {
                     rs->sr_err = slap_map_api2result( rs );

                     /* internal ops ( op->o_conn == NULL ) 
                      * must not reply to client */
                     if ( op->o_conn && !op->o_do_not_cache && matched ) {

                            /* record the (massaged) matched
                             * DN into the reply structure */
                            rs->sr_matched = matched;
                     }
              }

              if ( META_BACK_TGT_QUARANTINE( mt ) ) {
                     meta_back_quarantine( op, rs, candidate );
              }

       } else {
              int    i,
                     err = rs->sr_err;

              for ( i = 0; i < mi->mi_ntargets; i++ ) {
                     metasingleconn_t     *msc = &mc->mc_conns[ i ];
                     char                 *xtext = NULL;
                     char                 *xmatched = NULL;

                     if ( msc->msc_ld == NULL ) {
                            continue;
                     }

                     rs->sr_err = LDAP_SUCCESS;

                     ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE, &rs->sr_err );
                     if ( rs->sr_err != LDAP_SUCCESS ) {
                            /*
                             * better check the type of error. In some cases
                             * (search ?) it might be better to return a
                             * success if at least one of the targets gave
                             * positive result ...
                             */
                            ldap_get_option( msc->msc_ld,
                                          LDAP_OPT_DIAGNOSTIC_MESSAGE, &xtext );
                            if ( xtext != NULL && xtext [ 0 ] == '\0' ) {
                                   ldap_memfree( xtext );
                                   xtext = NULL;
                            }

                            ldap_get_option( msc->msc_ld,
                                          LDAP_OPT_MATCHED_DN, &xmatched );
                            if ( xmatched != NULL && xmatched[ 0 ] == '\0' ) {
                                   ldap_memfree( xmatched );
                                   xmatched = NULL;
                            }

                            rs->sr_err = slap_map_api2result( rs );
       
                            if ( LogTest( LDAP_DEBUG_ANY ) ) {
                                   char   buf[ SLAP_TEXT_BUFLEN ];

                                   snprintf( buf, sizeof( buf ),
                                          "meta_back_op_result[%d] "
                                          "err=%d text=\"%s\" matched=\"%s\"", 
                                          i, rs->sr_err,
                                          ( xtext ? xtext : "" ),
                                          ( xmatched ? xmatched : "" ) );
                                   Debug( LDAP_DEBUG_ANY, "%s %s.\n",
                                          op->o_log_prefix, buf, 0 );
                            }

                            /*
                             * FIXME: need to rewrite "match" (need rwinfo)
                             */
                            switch ( rs->sr_err ) {
                            default:
                                   err = rs->sr_err;
                                   if ( xtext != NULL ) {
                                          if ( text ) {
                                                 ldap_memfree( text );
                                          }
                                          text = xtext;
                                          xtext = NULL;
                                   }
                                   if ( xmatched != NULL ) {
                                          if ( matched ) {
                                                 ldap_memfree( matched );
                                          }
                                          matched = xmatched;
                                          xmatched = NULL;
                                   }
                                   break;
                            }

                            if ( xtext ) {
                                   ldap_memfree( xtext );
                            }
       
                            if ( xmatched ) {
                                   ldap_memfree( xmatched );
                            }
                     }

                     if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
                            meta_back_quarantine( op, rs, i );
                     }
              }

              if ( err != LDAP_SUCCESS ) {
                     rs->sr_err = err;
              }
       }

       if ( matched != NULL ) {
              struct berval dn, pdn;

              ber_str2bv( matched, 0, 0, &dn );
              if ( dnPretty( NULL, &dn, &pdn, op->o_tmpmemctx ) == LDAP_SUCCESS ) {
                     ldap_memfree( matched );
                     matched_ctx = op->o_tmpmemctx;
                     matched = pdn.bv_val;
              }
              rs->sr_matched = matched;
       }

       if ( rs->sr_err == LDAP_UNAVAILABLE ) {
              if ( !( sendok & LDAP_BACK_RETRYING ) ) {
                     if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
                            if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed";
                            send_ldap_result( op, rs );
                     }
              }

       } else if ( op->o_conn &&
              ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
                     || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
       {
              send_ldap_result( op, rs );
       }
       if ( matched ) {
              op->o_tmpfree( (char *)rs->sr_matched, matched_ctx );
       }
       if ( text ) {
              ldap_memfree( text );
       }
       if ( rs->sr_ref ) {
              op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
              rs->sr_ref = NULL;
       }
       if ( refs ) {
              ber_memvfree( (void **)refs );
       }
       if ( ctrls ) {
              assert( rs->sr_ctrls != NULL );
              ldap_controls_free( ctrls );
       }

       rs->sr_text = save_text;
       rs->sr_matched = save_matched;
       rs->sr_ref = save_ref;
       rs->sr_ctrls = save_ctrls;

       return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_proxy_authz_cred ( metaconn_t mc,
int  candidate,
Operation op,
SlapReply rs,
ldap_back_send_t  sendok,
struct berval binddn,
struct berval bindcred,
int method 
)

Definition at line 1298 of file bind.c.

{
       metainfo_t           *mi = (metainfo_t *)op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];
       struct berval        ndn;
       int                  dobind = 0;

       /* don't proxyAuthz if protocol is not LDAPv3 */
       switch ( mt->mt_version ) {
       case LDAP_VERSION3:
              break;

       case 0:
              if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
                     break;
              }
              /* fall thru */

       default:
              rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
              if ( sendok & LDAP_BACK_SENDERR ) {
                     send_ldap_result( op, rs );
              }
              LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
              goto done;
       }

       if ( op->o_tag == LDAP_REQ_BIND ) {
              ndn = op->o_req_ndn;

       } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
              ndn = op->o_conn->c_ndn;

       } else {
              ndn = op->o_ndn;
       }
       rs->sr_err = LDAP_SUCCESS;

       /*
        * FIXME: we need to let clients use proxyAuthz
        * otherwise we cannot do symmetric pools of servers;
        * we have to live with the fact that a user can
        * authorize itself as any ID that is allowed
        * by the authzTo directive of the "proxyauthzdn".
        */
       /*
        * NOTE: current Proxy Authorization specification
        * and implementation do not allow proxy authorization
        * control to be provided with Bind requests
        */
       /*
        * if no bind took place yet, but the connection is bound
        * and the "proxyauthzdn" is set, then bind as 
        * "proxyauthzdn" and explicitly add the proxyAuthz 
        * control to every operation with the dn bound 
        * to the connection as control value.
        */

       /* bind as proxyauthzdn only if no idassert mode
        * is requested, or if the client's identity
        * is authorized */
       switch ( mt->mt_idassert_mode ) {
       case LDAP_BACK_IDASSERT_LEGACY:
              if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) {
                     if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) )
                     {
                            *binddn = mt->mt_idassert_authcDN;
                            *bindcred = mt->mt_idassert_passwd;
                            dobind = 1;
                     }
              }
              break;

       default:
              /* NOTE: rootdn can always idassert */
              if ( BER_BVISNULL( &ndn )
                     && mt->mt_idassert_authz == NULL
                     && !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
              {
                     if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
                            rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
                            if ( sendok & LDAP_BACK_SENDERR ) {
                                   send_ldap_result( op, rs );
                            }
                            LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
                            goto done;

                     }

                     rs->sr_err = LDAP_SUCCESS;
                     *binddn = slap_empty_bv;
                     *bindcred = slap_empty_bv;
                     break;

              } else if ( mt->mt_idassert_authz && !be_isroot( op ) ) {
                     struct berval authcDN;

                     if ( BER_BVISNULL( &ndn ) ) {
                            authcDN = slap_empty_bv;

                     } else {
                            authcDN = ndn;
                     }      
                     rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz,
                                   &authcDN, &authcDN );
                     if ( rs->sr_err != LDAP_SUCCESS ) {
                            if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
                                   if ( sendok & LDAP_BACK_SENDERR ) {
                                          send_ldap_result( op, rs );
                                   }
                                   LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
                                   goto done;
                            }

                            rs->sr_err = LDAP_SUCCESS;
                            *binddn = slap_empty_bv;
                            *bindcred = slap_empty_bv;
                            break;
                     }
              }

              *binddn = mt->mt_idassert_authcDN;
              *bindcred = mt->mt_idassert_passwd;
              dobind = 1;
              break;
       }

       if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) {
#ifdef HAVE_CYRUS_SASL
              void          *defaults = NULL;
              struct berval authzID = BER_BVNULL;
              int           freeauthz = 0;

              /* if SASL supports native authz, prepare for it */
              if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) &&
                            ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
              {
                     switch ( mt->mt_idassert_mode ) {
                     case LDAP_BACK_IDASSERT_OTHERID:
                     case LDAP_BACK_IDASSERT_OTHERDN:
                            authzID = mt->mt_idassert_authzID;
                            break;

                     case LDAP_BACK_IDASSERT_ANONYMOUS:
                            BER_BVSTR( &authzID, "dn:" );
                            break;

                     case LDAP_BACK_IDASSERT_SELF:
                            if ( BER_BVISNULL( &ndn ) ) {
                                   /* connection is not authc'd, so don't idassert */
                                   BER_BVSTR( &authzID, "dn:" );
                                   break;
                            }
                            authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
                            authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx );
                            AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
                            AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ),
                                          ndn.bv_val, ndn.bv_len + 1 );
                            freeauthz = 1;
                            break;

                     default:
                            break;
                     }
              }

              if ( mt->mt_idassert_secprops != NULL ) {
                     rs->sr_err = ldap_set_option( msc->msc_ld,
                            LDAP_OPT_X_SASL_SECPROPS,
                            (void *)mt->mt_idassert_secprops );

                     if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
                            rs->sr_err = LDAP_OTHER;
                            if ( sendok & LDAP_BACK_SENDERR ) {
                                   send_ldap_result( op, rs );
                            }
                            LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
                            goto done;
                     }
              }

              defaults = lutil_sasl_defaults( msc->msc_ld,
                            mt->mt_idassert_sasl_mech.bv_val,
                            mt->mt_idassert_sasl_realm.bv_val,
                            mt->mt_idassert_authcID.bv_val,
                            mt->mt_idassert_passwd.bv_val,
                            authzID.bv_val );
              if ( defaults == NULL ) {
                     rs->sr_err = LDAP_OTHER;
                     LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
                     if ( sendok & LDAP_BACK_SENDERR ) {
                            send_ldap_result( op, rs );
                     }
                     goto done;
              }

              rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
                            mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
                            LDAP_SASL_QUIET, lutil_sasl_interact,
                            defaults );

              rs->sr_err = slap_map_api2result( rs );
              if ( rs->sr_err != LDAP_SUCCESS ) {
                     LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
                     if ( sendok & LDAP_BACK_SENDERR ) {
                            send_ldap_result( op, rs );
                     }

              } else {
                     LDAP_BACK_CONN_ISBOUND_SET( msc );
              }

              lutil_sasl_freedefs( defaults );
              if ( freeauthz ) {
                     slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
              }

              goto done;
#endif /* HAVE_CYRUS_SASL */
       }

       *method = mt->mt_idassert_authmethod;
       switch ( mt->mt_idassert_authmethod ) {
       case LDAP_AUTH_NONE:
              BER_BVSTR( binddn, "" );
              BER_BVSTR( bindcred, "" );
              /* fallthru */

       case LDAP_AUTH_SIMPLE:
              break;

       default:
              /* unsupported! */
              LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
              rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
              if ( sendok & LDAP_BACK_SENDERR ) {
                     send_ldap_result( op, rs );
              }
              break;
       }

done:;

       if ( !BER_BVISEMPTY( binddn ) ) {
              LDAP_BACK_CONN_ISIDASSERT_SET( msc );
       }

       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void meta_back_quarantine ( Operation op,
SlapReply rs,
int  candidate 
)

Definition at line 1820 of file conn.c.

{
       metainfo_t           *mi = (metainfo_t *)op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];

       slap_retry_info_t    *ri = &mt->mt_quarantine;

       ldap_pvt_thread_mutex_lock( &mt->mt_quarantine_mutex );

       if ( rs->sr_err == LDAP_UNAVAILABLE ) {
              time_t new_last = slap_get_time();

              switch ( mt->mt_isquarantined ) {
              case LDAP_BACK_FQ_NO:
                     if ( ri->ri_last == new_last ) {
                            goto done;
                     }

                     Debug( LDAP_DEBUG_ANY,
                            "%s meta_back_quarantine[%d]: enter.\n",
                            op->o_log_prefix, candidate, 0 );

                     ri->ri_idx = 0;
                     ri->ri_count = 0;
                     break;

              case LDAP_BACK_FQ_RETRYING:
                     if ( LogTest( LDAP_DEBUG_ANY ) ) {
                            char   buf[ SLAP_TEXT_BUFLEN ];

                            snprintf( buf, sizeof( buf ),
                                   "meta_back_quarantine[%d]: block #%d try #%d failed",
                                   candidate, ri->ri_idx, ri->ri_count );
                            Debug( LDAP_DEBUG_ANY, "%s %s.\n",
                                   op->o_log_prefix, buf, 0 );
                     }

                     ++ri->ri_count;
                     if ( ri->ri_num[ ri->ri_idx ] != SLAP_RETRYNUM_FOREVER
                            && ri->ri_count == ri->ri_num[ ri->ri_idx ] )
                     {
                            ri->ri_count = 0;
                            ++ri->ri_idx;
                     }
                     break;

              default:
                     break;
              }

              mt->mt_isquarantined = LDAP_BACK_FQ_YES;
              ri->ri_last = new_last;

       } else if ( mt->mt_isquarantined == LDAP_BACK_FQ_RETRYING ) {
              Debug( LDAP_DEBUG_ANY,
                     "%s meta_back_quarantine[%d]: exit.\n",
                     op->o_log_prefix, candidate, 0 );

              if ( mi->mi_quarantine_f ) {
                     (void)mi->mi_quarantine_f( mi, candidate,
                            mi->mi_quarantine_p );
              }

              ri->ri_count = 0;
              ri->ri_idx = 0;
              mt->mt_isquarantined = LDAP_BACK_FQ_NO;
       }

done:;
       ldap_pvt_thread_mutex_unlock( &mt->mt_quarantine_mutex );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void meta_back_release_conn_lock ( metainfo_t mi,
metaconn_t mc,
int  dolock 
)

Definition at line 1753 of file conn.c.

{
       assert( mc != NULL );

       if ( dolock ) {
              ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
       }
       assert( mc->mc_refcnt > 0 );
       mc->mc_refcnt--;
       /* NOTE: the connection is removed if either it is tainted
        * or if it is shared and no one else is using it.  This needs
        * to occur because for intrinsic reasons cached connections
        * that are not privileged would live forever and pollute
        * the connection space (and eat up resources).  Maybe this
        * should be configurable... */
       if ( LDAP_BACK_CONN_TAINTED( mc ) || !LDAP_BACK_CONN_CACHED( mc ) ) {
#if META_BACK_PRINT_CONNTREE > 0
              meta_back_print_conntree( mi, ">>> meta_back_release_conn" );
#endif /* META_BACK_PRINT_CONNTREE */

              if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
                     if ( mc->mc_q.tqe_prev != NULL ) {
                            assert( LDAP_BACK_CONN_CACHED( mc ) );
                            assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
                            LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv, mc, mc_q );
                            mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
                            LDAP_TAILQ_ENTRY_INIT( mc, mc_q );

                     } else {
                            assert( !LDAP_BACK_CONN_CACHED( mc ) );
                     }

              } else if ( LDAP_BACK_CONN_CACHED( mc ) ) {
                     metaconn_t    *tmpmc;

                     tmpmc = avl_delete( &mi->mi_conninfo.lai_tree,
                            ( caddr_t )mc, meta_back_conndnmc_cmp );

                     /* Overparanoid, but useful... */
                     assert( tmpmc == NULL || tmpmc == mc );
              }

              LDAP_BACK_CONN_CACHED_CLEAR( mc );

#if META_BACK_PRINT_CONNTREE > 0
              meta_back_print_conntree( mi, "<<< meta_back_release_conn" );
#endif /* META_BACK_PRINT_CONNTREE */

              if ( mc->mc_refcnt == 0 ) {
                     meta_back_conn_free( mc );
                     mc = NULL;
              }
       }

       if ( mc != NULL && LDAP_BACK_CONN_BINDING( mc ) ) {
              LDAP_BACK_CONN_BINDING_CLEAR( mc );
       }

       if ( dolock ) {
              ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_retry ( Operation op,
SlapReply rs,
metaconn_t **  mcp,
int  candidate,
ldap_back_send_t  sendok 
)

Definition at line 688 of file conn.c.

{
       metainfo_t           *mi = ( metainfo_t * )op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metaconn_t           *mc = *mcp;
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];
       int                  rc = LDAP_UNAVAILABLE,
                            binding,
                            quarantine = 1;

       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );

       assert( !META_BACK_CONN_CREATING( msc ) );
       binding = LDAP_BACK_CONN_BINDING( msc );
       LDAP_BACK_CONN_BINDING_CLEAR( msc );

       assert( mc->mc_refcnt > 0 );
       if ( mc->mc_refcnt == 1 ) {
              struct berval save_cred;

              if ( LogTest( LDAP_DEBUG_ANY ) ) {
                     char   buf[ SLAP_TEXT_BUFLEN ];

                     /* this lock is required; however,
                      * it's invoked only when logging is on */
                     ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
                     snprintf( buf, sizeof( buf ),
                            "retrying URI=\"%s\" DN=\"%s\"",
                            mt->mt_uri,
                            BER_BVISNULL( &msc->msc_bound_ndn ) ?
                                   "" : msc->msc_bound_ndn.bv_val );
                     ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );

                     Debug( LDAP_DEBUG_ANY,
                            "%s meta_back_retry[%d]: %s.\n",
                            op->o_log_prefix, candidate, buf );
              }

              /* save credentials, if any, for later use;
               * meta_clear_one_candidate() would free them */
              save_cred = msc->msc_cred;
              BER_BVZERO( &msc->msc_cred );

              meta_clear_one_candidate( op, mc, candidate );
              LDAP_BACK_CONN_ISBOUND_CLEAR( msc );

              ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );

              /* mc here must be the regular mc, reset and ready for init */
              rc = meta_back_init_one_conn( op, rs, mc, candidate,
                     LDAP_BACK_CONN_ISPRIV( mc ), sendok, 0 );

              /* restore credentials, if any and if needed;
               * meta_back_init_one_conn() restores msc_bound_ndn, if any;
               * if no msc_bound_ndn is restored, destroy credentials */
              if ( !BER_BVISNULL( &msc->msc_bound_ndn )
                     && BER_BVISNULL( &msc->msc_cred ) )
              {
                     msc->msc_cred = save_cred;

              } else if ( !BER_BVISNULL( &save_cred ) ) {
                     memset( save_cred.bv_val, 0, save_cred.bv_len );
                     ber_memfree_x( save_cred.bv_val, NULL );
              }

              /* restore the "binding" flag, in case */
              if ( binding ) {
                     LDAP_BACK_CONN_BINDING_SET( msc );
              }

              if ( rc == LDAP_SUCCESS ) {
                     quarantine = 0;
                     rc = meta_back_single_dobind( op, rs, mcp, candidate,
                            sendok, mt->mt_nretries, 0 );

                     Debug( LDAP_DEBUG_ANY,
                            "%s meta_back_retry[%d]: "
                            "meta_back_single_dobind=%d\n",
                            op->o_log_prefix, candidate, rc );
                     if ( rc == LDAP_SUCCESS ) {
                            if ( !BER_BVISNULL( &msc->msc_bound_ndn ) &&
                                   !BER_BVISEMPTY( &msc->msc_bound_ndn ) )
                            {
                                   LDAP_BACK_CONN_ISBOUND_SET( msc );

                            } else {
                                   LDAP_BACK_CONN_ISANON_SET( msc );
                            }

                            /* when bound, dispose of the "binding" flag */
                            if ( binding ) {
                                   LDAP_BACK_CONN_BINDING_CLEAR( msc );
                            }
                     }
              }

              /* don't send twice */
              sendok &= ~LDAP_BACK_SENDERR;
       }

       if ( rc != LDAP_SUCCESS ) {
              SlapReply            *candidates = meta_back_candidates_get( op );

              candidates[ candidate ].sr_err = rc;

              if ( *mcp != NULL ) {
                     if ( mc->mc_refcnt == 1 ) {
                            if ( binding ) {
                                   LDAP_BACK_CONN_BINDING_CLEAR( msc );
                            }
                            (void)meta_clear_one_candidate( op, mc, candidate );
                     }

                     LDAP_BACK_CONN_TAINTED_SET( mc );
                     /* only release if mandatory; otherwise
                      * let the caller do what's best before
                      * releasing */
                     if ( META_BACK_ONERR_STOP( mi ) ) {
                            meta_back_release_conn_lock( mi, mc, 0 );
                            *mcp = NULL;

                     } else {
#if META_BACK_PRINT_CONNTREE > 0
                            meta_back_print_conntree( mi, ">>> meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */

                            /* FIXME: could be done better, reworking meta_back_release_conn_lock() */
                            if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
                                   if ( mc->mc_q.tqe_prev != NULL ) {
                                          assert( LDAP_BACK_CONN_CACHED( mc ) );
                                          assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
                                          LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
                                                 mc, mc_q );
                                          mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
                                          LDAP_TAILQ_ENTRY_INIT( mc, mc_q );

                                   } else {
                                          assert( !LDAP_BACK_CONN_CACHED( mc ) );
                                   }

                            } else {
                                   /* FIXME: check if in tree, for consistency? */
                                   (void)avl_delete( &mi->mi_conninfo.lai_tree,
                                          ( caddr_t )mc, meta_back_conndnmc_cmp );
                            }
                            LDAP_BACK_CONN_CACHED_CLEAR( mc );

#if META_BACK_PRINT_CONNTREE > 0
                            meta_back_print_conntree( mi, "<<< meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */
                     }
              }

              if ( sendok & LDAP_BACK_SENDERR ) {
                     rs->sr_err = rc;
                     rs->sr_text = "Unable to retry";
                     send_ldap_result( op, rs );
              }
       }

       if ( quarantine && META_BACK_TGT_QUARANTINE( mt ) ) {
              meta_back_quarantine( op, rs, candidate );
       }

       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

       return rc == LDAP_SUCCESS ? 1 : 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 195 of file candidates.c.

{
       int    i, candidate = META_TARGET_NONE;

       for ( i = 0; i < mi->mi_ntargets; i++ ) {
              metatarget_t  *mt = mi->mi_targets[ i ];

              if ( meta_back_is_candidate( mt, ndn, LDAP_SCOPE_BASE ) ) {
                     if ( candidate == META_TARGET_NONE ) {
                            candidate = i;

                     } else {
                            return META_TARGET_MULTIPLE;
                     }
              }
       }

       return candidate;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_back_single_dobind ( Operation op,
SlapReply rs,
metaconn_t **  mcp,
int  candidate,
ldap_back_send_t  sendok,
int  retries,
int  dolock 
)

Definition at line 580 of file bind.c.

{
       metainfo_t           *mi = ( metainfo_t * )op->o_bd->be_private;
       metatarget_t         *mt = mi->mi_targets[ candidate ];
       metaconn_t           *mc = *mcp;
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];
       int                  msgid;

       assert( !LDAP_BACK_CONN_ISBOUND( msc ) );

       /* NOTE: this obsoletes pseudorootdn */
       if ( op->o_conn != NULL &&
              !op->o_do_not_cache &&
              ( BER_BVISNULL( &msc->msc_bound_ndn ) ||
                     BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
                     ( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
                     ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
       {
              (void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok, dolock );

       } else {
              char *binddn = "";
              struct berval cred = BER_BVC( "" );

              /* use credentials if available */
              if ( !BER_BVISNULL( &msc->msc_bound_ndn )
                     && !BER_BVISNULL( &msc->msc_cred ) )
              {
                     binddn = msc->msc_bound_ndn.bv_val;
                     cred = msc->msc_cred;
              }

              /* FIXME: should we check if at least some of the op->o_ctrls
               * can/should be passed? */
              for (;;) {
                     rs->sr_err = ldap_sasl_bind( msc->msc_ld,
                            binddn, LDAP_SASL_SIMPLE, &cred,
                            NULL, NULL, &msgid );
                     if ( rs->sr_err != LDAP_X_CONNECTING ) {
                            break;
                     }
                     ldap_pvt_thread_yield();
              }

              rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok, dolock );

              /* if bind succeeded, but anonymous, clear msc_bound_ndn */
              if ( rs->sr_err != LDAP_SUCCESS || binddn[0] == '\0' ) {
                     if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
                            ber_memfree( msc->msc_bound_ndn.bv_val );
                            BER_BVZERO( &msc->msc_bound_ndn );
                     }

                     if ( !BER_BVISNULL( &msc->msc_cred ) ) {
                            memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
                            ber_memfree( msc->msc_cred.bv_val );
                            BER_BVZERO( &msc->msc_cred );
                     }
              }
       }

       if ( rs->sr_err != LDAP_SUCCESS ) {
              if ( dolock ) {
                     ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
              }
              LDAP_BACK_CONN_BINDING_CLEAR( msc );
              if ( META_BACK_ONERR_STOP( mi ) ) {
                     LDAP_BACK_CONN_TAINTED_SET( mc );
                     meta_back_release_conn_lock( mi, mc, 0 );
                     *mcp = NULL;
              }
              if ( dolock ) {
                     ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
              }
       }

       if ( META_BACK_TGT_QUARANTINE( mt ) ) {
              meta_back_quarantine( op, rs, candidate );
       }

       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_clear_one_candidate ( Operation op,
metaconn_t mc,
int  candidate 
)

Definition at line 247 of file candidates.c.

{
       metasingleconn_t     *msc = &mc->mc_conns[ candidate ];

       if ( msc->msc_ld != NULL ) {

#ifdef DEBUG_205
              char   buf[ BUFSIZ ];

              snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p",
                     candidate, (void *)mc, (void *)msc->msc_ld );
              Debug( LDAP_DEBUG_ANY, "### %s %s\n",
                     op ? op->o_log_prefix : "", buf, 0 );
#endif /* DEBUG_205 */

              ldap_unbind_ext( msc->msc_ld, NULL, NULL );
              msc->msc_ld = NULL;
       }

       if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
              ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
              BER_BVZERO( &msc->msc_bound_ndn );
       }

       if ( !BER_BVISNULL( &msc->msc_cred ) ) {
              memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
              ber_memfree_x( msc->msc_cred.bv_val, NULL );
              BER_BVZERO( &msc->msc_cred );
       }

       msc->msc_mscflags = 0;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int meta_clear_unused_candidates ( Operation op,
int  candidate 
)

Definition at line 223 of file candidates.c.

{
       metainfo_t    *mi = ( metainfo_t * )op->o_bd->be_private;
       int           i;
       SlapReply     *candidates = meta_back_candidates_get( op );
       
       for ( i = 0; i < mi->mi_ntargets; ++i ) {
              if ( i == candidate ) {
                     continue;
              }
              META_CANDIDATE_RESET( &candidates[ i ] );
       }

       return 0;
}

Here is the call graph for this function:

int meta_dncache_cmp ( const void c1,
const void c2 
)

Definition at line 51 of file dncache.c.

{
       metadncacheentry_t   *cc1 = ( metadncacheentry_t * )c1;
       metadncacheentry_t   *cc2 = ( metadncacheentry_t * )c2;

       /*
        * case sensitive, because the dn MUST be normalized
        */
       return ber_bvcmp( &cc1->dn, &cc2->dn);
}

Here is the caller graph for this function:

int meta_dncache_delete_entry ( metadncache_t cache,
struct berval ndn 
)

Definition at line 199 of file dncache.c.

{
       metadncacheentry_t   *entry,
                            tmp_entry;

       assert( cache != NULL );
       assert( ndn != NULL );

       tmp_entry.dn = *ndn;

       ldap_pvt_thread_mutex_lock( &cache->mutex );
       entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
                     meta_dncache_cmp );
       ldap_pvt_thread_mutex_unlock( &cache->mutex );

       if ( entry != NULL ) {
              meta_dncache_free( ( void * )entry );
       }

       return 0;
}

Here is the call graph for this function:

int meta_dncache_dup ( void c1,
void c2 
)

Definition at line 71 of file dncache.c.

{
       metadncacheentry_t   *cc1 = ( metadncacheentry_t * )c1;
       metadncacheentry_t   *cc2 = ( metadncacheentry_t * )c2;
       
       /*
        * case sensitive, because the dn MUST be normalized
        */
       return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0;
}

Here is the caller graph for this function:

void meta_dncache_free ( void entry)

Definition at line 230 of file dncache.c.

{
       free( e );
}

Here is the caller graph for this function:

int meta_dncache_get_target ( metadncache_t cache,
struct berval ndn 
)

Definition at line 91 of file dncache.c.

{
       metadncacheentry_t   tmp_entry,
                            *entry;
       int                  target = META_TARGET_NONE;

       assert( cache != NULL );
       assert( ndn != NULL );

       tmp_entry.dn = *ndn;
       ldap_pvt_thread_mutex_lock( &cache->mutex );
       entry = ( metadncacheentry_t * )avl_find( cache->tree,
                     ( caddr_t )&tmp_entry, meta_dncache_cmp );

       if ( entry != NULL ) {
              
              /*
               * if cache->ttl < 0, cache never expires;
               * if cache->ttl = 0 no cache is used; shouldn't get here
               * else, cache is used with ttl
               */
              if ( cache->ttl < 0 ) { 
                     target = entry->target;

              } else {
                     if ( entry->lastupdated+cache->ttl > slap_get_time() ) {
                            target = entry->target;
                     }
              }
       }
       ldap_pvt_thread_mutex_unlock( &cache->mutex );

       return target;
}

Here is the call graph for this function:

int meta_dncache_update_entry ( metadncache_t cache,
struct berval ndn,
int  target 
)

Definition at line 135 of file dncache.c.

{
       metadncacheentry_t   *entry,
                            tmp_entry;
       time_t               curr_time = 0L;
       int                  err = 0;

       assert( cache != NULL );
       assert( ndn != NULL );

       /*
        * if cache->ttl < 0, cache never expires;
        * if cache->ttl = 0 no cache is used; shouldn't get here
        * else, cache is used with ttl
        */
       if ( cache->ttl > 0 ) {
              curr_time = slap_get_time();
       }

       tmp_entry.dn = *ndn;

       ldap_pvt_thread_mutex_lock( &cache->mutex );
       entry = ( metadncacheentry_t * )avl_find( cache->tree,
                     ( caddr_t )&tmp_entry, meta_dncache_cmp );

       if ( entry != NULL ) {
              entry->target = target;
              entry->lastupdated = curr_time;

       } else {
              entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
              if ( entry == NULL ) {
                     err = -1;
                     goto error_return;
              }

              entry->dn.bv_len = ndn->bv_len;
              entry->dn.bv_val = (char *)&entry[ 1 ];
              AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len );
              entry->dn.bv_val[ ndn->bv_len ] = '\0';

              entry->target = target;
              entry->lastupdated = curr_time;

              err = avl_insert( &cache->tree, ( caddr_t )entry,
                            meta_dncache_cmp, meta_dncache_dup );
       }

error_return:;
       ldap_pvt_thread_mutex_unlock( &cache->mutex );

       return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 96 of file config.c.

{
       if ( ms->ms_next ) {
              meta_subtree_destroy( ms->ms_next );
       }

       switch ( ms->ms_type ) {
       case META_ST_SUBTREE:
       case META_ST_SUBORDINATE:
              ber_memfree( ms->ms_dn.bv_val );
              break;

       case META_ST_REGEX:
              regfree( &ms->ms_regex );
              ch_free( ms->ms_regex_pattern );
              break;

       default:
              return -1;
       }

       ch_free( ms );

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

LDAP_REBIND_PROC meta_back_default_rebind
LDAP_URLLIST_PROC meta_back_default_urllist