]> git.sur5r.net Git - openldap/commitdiff
Sync with head
authorKurt Zeilenga <kurt@openldap.org>
Sat, 10 Aug 2002 00:19:39 +0000 (00:19 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Sat, 10 Aug 2002 00:19:39 +0000 (00:19 +0000)
16 files changed:
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/group.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h [new file with mode: 0644]
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c [new file with mode: 0644]
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/group.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-meta/unbind.c
servers/slapd/back-monitor/conn.c

index f0ea612e8137575f1134c18bca2b534c610b0224..42e44659bfd049f8a02f4155f16d5227871b39f9 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "slap.h"
 #include "back-ldap.h"
+#include "lutil.h"
 
 int
 ldap_back_db_config(
@@ -430,10 +431,40 @@ suffix_massage_config(
                 * walk the filter looking for DN-valued attributes,
                 * and only rewrite those that require rewriting
                 */
-               char vbuf[LDAP_FILT_MAXSIZ], rbuf[LDAP_FILT_MAXSIZ];
+               char    vbuf_[BUFSIZ], *vbuf = vbuf_,
+                       rbuf_[BUFSIZ], *rbuf = rbuf_;
+               int     len;
+
+               len = snprintf( vbuf, sizeof( vbuf_ ), 
+                               "(.*)%s\\)(.*)", nvnc->bv_val );
+               if ( len == -1 ) {
+                       /* 
+                        * traditional behavior: snprintf returns -1 
+                        * if buffer is insufficient
+                        */
+                       return -1;
+
+               } else if ( len >= sizeof( vbuf_ ) ) {
+                       /* 
+                        * C99: snprintf returns the required size 
+                        */
+                       vbuf = ch_malloc( len + 1 );
+                       len = snprintf( vbuf, len,
+                                       "(.*)%s\\)(.*)", nvnc->bv_val );
+                       assert( len > 0 );
+               }
+
+               len = snprintf( rbuf, sizeof( rbuf_ ), "%%1%s)%%2", 
+                               nrnc->bv_val );
+               if ( len == -1 ) {
+                       return -1;
 
-               snprintf( vbuf, sizeof( vbuf ), "(.*)%s\\)(.*)", nvnc->bv_val );
-               snprintf( rbuf, sizeof( rbuf ), "%%1%s)%%2", nrnc->bv_val );
+               } else if ( len >= sizeof( rbuf_ ) ) {
+                       rbuf = ch_malloc( len + 1 );
+                       len = snprintf( rbuf, sizeof( rbuf_ ), "%%1%s)%%2", 
+                                       nrnc->bv_val );
+                       assert( len > 0 );
+               }
                
                rargv[ 0 ] = "rewriteRule";
                rargv[ 1 ] = vbuf;
@@ -441,6 +472,14 @@ suffix_massage_config(
                rargv[ 3 ] = ":";
                rargv[ 4 ] = NULL;
                rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
+
+               if ( vbuf != vbuf_ ) {
+                       ch_free( vbuf );
+               }
+
+               if ( rbuf != rbuf_ ) {
+                       ch_free( rbuf );
+               }
        }
 #endif /* rewrite filters */
 
index 16a2c5046ec62d5d3819425b46823ccdeb4bd961..5581cdfc642a30418a4f41da49316140748ce830 100644 (file)
@@ -14,7 +14,7 @@
 
 #include "slap.h"
 #include "back-ldap.h"
-
+#include "lutil.h"
 
 /* return 0 IFF op_dn is a value in group_at (member) attribute
  * of entry with gr_dn AND that entry has an objectClass
index 1c87903f451e843188468596038fb64bb74dd47e..58555bbdfebd9b9e4d246ef7ebf6edf7d9f8cd4a 100644 (file)
@@ -200,7 +200,7 @@ meta_back_add(
        }
        attrs[ i ] = NULL;
 
-       ldap_add_s( lc->conns[ candidate ]->ld, mdn.bv_val, attrs );
+       ldap_add_s( lc->conns[ candidate ].ld, mdn.bv_val, attrs );
        for ( --i; i >= 0; --i ) {
                free( attrs[ i ]->mod_vals.modv_bvals );
                free( attrs[ i ] );
diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h
new file mode 100644 (file)
index 0000000..3bf9285
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ *
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
+ *
+ * This work has been developed to fulfill the requirements
+ * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
+ * to the OpenLDAP Foundation in the hope that it may be useful
+ * to the Open Source community, but WITHOUT ANY WARRANTY.
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author and SysNet s.n.c. are not responsible for the consequences
+ *    of use of this software, no matter how awful, even if they arise from 
+ *    flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ *    explicit claim or by omission.  Since few users ever read sources,
+ *    credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.  Since few users
+ *    ever read sources, credits should appear in the documentation.
+ *    SysNet s.n.c. cannot be responsible for the consequences of the
+ *    alterations.
+ *                         
+ * 4. This notice may not be removed or altered.
+ *
+ *
+ * This software is based on the backend back-ldap, implemented
+ * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
+ * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
+ * contributors. The contribution of the original software to the present
+ * implementation is acknowledged in this copyright statement.
+ *
+ * A special acknowledgement goes to Howard for the overall architecture
+ * (and for borrowing large pieces of code), and to Mark, who implemented
+ * from scratch the attribute/objectclass mapping.
+ *
+ * The original copyright statement follows.
+ *
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ *    software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ *    explicit claim or by omission.  Since few users ever read sources,
+ *    credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.  Since few users
+ *    ever read sources, credits should appear in the
+ *    documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ *                
+ */ 
+
+#ifndef SLAPD_LDAP_H
+#error "include servers/slapd/back-ldap/back-ldap.h before this file!"
+#endif /* SLAPD_LDAP_H */
+
+#ifndef SLAPD_META_H
+#define SLAPD_META_H
+
+#include "external.h"
+
+/* String rewrite library */
+#include "rewrite.h"
+
+LDAP_BEGIN_DECL
+
+struct slap_conn;
+struct slap_op;
+
+struct metasingleconn {
+       int                     candidate;
+#define        META_NOT_CANDIDATE      0
+#define        META_CANDIDATE          1
+#define        META_LAST_CONN          -1
+       
+       LDAP                    *ld;
+       struct berval           bound_dn;
+       int                     bound;
+#define META_UNBOUND           0
+#define META_BOUND             1
+#define META_ANONYMOUS         2
+};
+
+#define META_LAST(lsc)         ((lsc)->candidate == META_LAST_CONN)
+
+struct metaconn {
+       struct slap_conn        *conn;
+       struct rewrite_info     *rwinfo;
+       
+       /*
+        * means that the connection is bound; 
+        * of course only one target actually is ...
+        */
+       int             bound_target;
+#define META_BOUND_NONE                -1
+#define META_BOUND_ALL         -2
+       /* supersedes the connection stuff */
+       struct metasingleconn *conns;
+};
+
+struct metatarget {
+       char                    *uri;
+       struct berval           psuffix;        /* pretty suffix */
+       struct berval           suffix;         /* normalized suffix */
+       struct berval           binddn;
+       struct berval           bindpw;
+
+       struct berval           pseudorootdn;
+       struct berval           pseudorootpw;
+
+       struct rewrite_info     *rwinfo;
+
+       struct ldapmap          oc_map;
+       struct ldapmap          at_map;
+};
+
+struct metadncache {
+       ldap_pvt_thread_mutex_t mutex;
+       Avlnode                 *tree;
+
+#define META_DNCACHE_DISABLED   0
+#define META_DNCACHE_FOREVER    -1
+       long int                ttl;  /* seconds; 0: no cache, -1: no expiry */
+};
+
+struct metainfo {
+       int                     ntargets;
+       int                     defaulttarget;
+#define META_DEFAULT_TARGET_NONE       -1
+       struct metatarget       **targets;
+
+       struct metadncache      cache;
+       
+       ldap_pvt_thread_mutex_t conn_mutex;
+       Avlnode                 *conntree;
+};
+
+extern int
+meta_back_do_single_bind(
+               struct metainfo         *li,
+               struct metaconn         *lc,
+               struct berval           *dn,
+               struct berval           *ndn,
+               struct berval           *cred,
+               int                     method,
+               int                     candidate
+);
+
+
+#define META_OP_ALLOW_MULTIPLE         0x00
+#define META_OP_REQUIRE_SINGLE         0x01
+#define META_OP_REQUIRE_ALL            0x02
+extern struct metaconn *
+meta_back_getconn(
+               struct                  metainfo *li,
+               struct                  slap_conn *conn,
+               struct                  slap_op *op,
+               int                     op_type,
+               struct berval           *dn,
+               int                     *candidate
+);
+
+extern int
+meta_back_dobind(
+               struct metaconn         *lc,
+               Operation               *op
+);
+
+extern int
+meta_back_is_valid(
+               struct metaconn         *lc, 
+               int                     candidate 
+);
+
+extern int
+meta_back_op_result(
+               struct metaconn         *lc,
+               Operation               *op
+);
+
+extern int
+back_meta_LTX_init_module(
+               int                     argc,
+               char                    *argv[]
+);
+
+extern int
+meta_back_conn_cmp(
+               const void              *c1,
+               const void              *c2
+);
+
+extern int
+meta_back_conn_dup(
+               void                    *c1,
+               void                    *c2
+);
+
+/*
+ * Candidate stuff
+ */
+extern int
+meta_back_is_candidate(
+               struct berval           *nsuffix,
+               struct berval           *ndn
+);
+
+extern int
+meta_back_count_candidates(
+               struct metainfo         *li,
+               struct berval           *ndn
+);
+
+extern int
+meta_back_is_candidate_unique(
+               struct metainfo         *li,
+               struct berval           *ndn
+);
+
+extern int
+meta_back_select_unique_candidate(
+               struct metainfo         *li,
+               struct berval           *ndn
+);
+
+extern int
+meta_clear_unused_candidates(
+               struct metainfo         *li,
+               struct metaconn         *lc,
+               int                     candidate,
+               int                     reallyclean
+);
+
+extern int
+meta_clear_one_candidate(
+               struct metasingleconn   *lc,
+               int                     reallyclean
+);
+
+/*
+ * Dn cache stuff (experimental)
+ */
+extern int
+meta_dncache_cmp(
+               const void              *c1,
+               const void              *c2
+);
+
+extern int
+meta_dncache_dup(
+               void                    *c1,
+               void                    *c2
+);
+
+extern int
+meta_dncache_get_target(
+               struct metadncache      *cache,
+               struct berval           *ndn
+);
+
+extern int
+meta_dncache_update_entry(
+               struct metadncache      *cache,
+               struct berval           *ndn,
+               int                     target
+);
+
+extern int
+meta_dncache_delete_entry(
+               struct metadncache      *cache,
+               struct berval           *ndn
+);
+
+extern void
+meta_dncache_free(
+               void *entry
+);
+
+LDAP_END_DECL
+
+#endif /* SLAPD_META_H */
+
index 1eb07531c3ee0f27d9d7ed9b0a46e1adf0330e70..8735d3e0946d836bcfdc21edc2d7d4c95f3d0a53 100644 (file)
@@ -140,7 +140,7 @@ meta_back_bind(
                /*
                 * Skip non-candidates
                 */
-               if ( lc->conns[ i ]->candidate != META_CANDIDATE ) {
+               if ( lc->conns[ i ].candidate != META_CANDIDATE ) {
                        continue;
                }
 
@@ -181,7 +181,7 @@ meta_back_bind(
                                realdn, realndn, realcred, realmethod, i );
                if ( lerr != LDAP_SUCCESS ) {
                        err = lerr;
-                       ( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+                       ( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
                } else {
                        rc = LDAP_SUCCESS;
                }
@@ -263,12 +263,12 @@ meta_back_do_single_bind(
                return LDAP_OTHER;
        }
 
-       rc = ldap_bind_s( lc->conns[ candidate ]->ld, mdn.bv_val, cred->bv_val, method );
+       rc = ldap_bind_s( lc->conns[ candidate ].ld, mdn.bv_val, cred->bv_val, method );
        if ( rc != LDAP_SUCCESS ) {
                rc = ldap_back_map_result( rc );
        } else {
-               ber_dupbv( &lc->conns[ candidate ]->bound_dn, dn );
-               lc->conns[ candidate ]->bound = META_BOUND;
+               ber_dupbv( &lc->conns[ candidate ].bound_dn, dn );
+               lc->conns[ candidate ].bound = META_BOUND;
                lc->bound_target = candidate;
 
                if ( li->cache.ttl != META_DNCACHE_DISABLED
@@ -291,7 +291,7 @@ meta_back_do_single_bind(
 int
 meta_back_dobind( struct metaconn *lc, Operation *op )
 {
-       struct metasingleconn **lsc;
+       struct metasingleconn *lsc;
        int bound = 0, i;
 
        /*
@@ -301,20 +301,20 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                return 1;
        }
 
-       for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+       for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
                int rc;
 
                /*
                 * Not a candidate or something wrong with this target ...
                 */
-               if ( lsc[ 0 ]->ld == NULL ) {
+               if ( lsc->ld == NULL ) {
                        continue;
                }
 
                /*
                 * If the target is already bound it is skipped
                 */
-               if ( lsc[ 0 ]->bound == META_BOUND && lc->bound_target == i ) {
+               if ( lsc->bound == META_BOUND && lc->bound_target == i ) {
                        ++bound;
                        continue;
                }
@@ -324,12 +324,12 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                 * (note: if the target was already bound, the anonymous
                 * bind clears the previous bind).
                 */
-               if ( lsc[ 0 ]->bound_dn.bv_val ) {
-                       ch_free( lsc[ 0 ]->bound_dn.bv_val );
-                       lsc[ 0 ]->bound_dn.bv_val = NULL;
-                       lsc[ 0 ]->bound_dn.bv_len = 0;
+               if ( lsc->bound_dn.bv_val ) {
+                       ch_free( lsc->bound_dn.bv_val );
+                       lsc->bound_dn.bv_val = NULL;
+                       lsc->bound_dn.bv_len = 0;
                }
-               rc = ldap_bind_s( lsc[ 0 ]->ld, 0, NULL, LDAP_AUTH_SIMPLE );
+               rc = ldap_bind_s( lsc->ld, 0, NULL, LDAP_AUTH_SIMPLE );
                if ( rc != LDAP_SUCCESS ) {
                        
 #ifdef NEW_LOGGING
@@ -337,14 +337,14 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                                        "meta_back_dobind: (anonymous)"
                                        " bind as \"%s\" failed"
                                        " with error \"%s\"\n",
-                                       lsc[ 0 ]->bound_dn.bv_val,
+                                       lsc->bound_dn.bv_val,
                                        ldap_err2string( rc ), 0 );
 #else /* !NEW_LOGGING */
                        Debug( LDAP_DEBUG_ANY,
                                        "==>meta_back_dobind: (anonymous)"
                                        " bind as \"%s\" failed"
                                        " with error \"%s\"\n%s",
-                                       lsc[ 0 ]->bound_dn.bv_val,
+                                       lsc->bound_dn.bv_val,
                                        ldap_err2string( rc ), "" );
 #endif /* !NEW_LOGGING */
 
@@ -355,11 +355,11 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                         * due to technical reasons (remote host down?)
                         * so better clear the handle
                         */
-                       ( void )meta_clear_one_candidate( lsc[ 0 ], 1 );
+                       ( void )meta_clear_one_candidate( lsc, 1 );
                        continue;
                } /* else */
                
-               lsc[ 0 ]->bound = META_ANONYMOUS;
+               lsc->bound = META_ANONYMOUS;
                ++bound;
        }
 
@@ -372,7 +372,7 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 int
 meta_back_is_valid( struct metaconn *lc, int candidate )
 {
-       struct metasingleconn   **lsc;
+       struct metasingleconn   *lsc;
        int                     i;
 
        assert( lc );
@@ -381,12 +381,11 @@ meta_back_is_valid( struct metaconn *lc, int candidate )
                return 0;
        }
 
-       for ( i = 0, lsc = lc->conns; 
-                       lsc[ 0 ] != NULL && i < candidate; 
+       for ( i = 0, lsc = lc->conns; !META_LAST(lsc) && i < candidate; 
                        ++i, ++lsc );
        
-       if ( lsc[ 0 ] ) {
-               return( lsc[ 0 ]->ld != NULL );
+       if ( !META_LAST(lsc) ) {
+               return( lsc->ld != NULL );
        }
 
        return 0;
@@ -399,16 +398,16 @@ int
 meta_back_op_result( struct metaconn *lc, Operation *op )
 {
        int i, rerr = LDAP_SUCCESS;
-       struct metasingleconn **lsc;
+       struct metasingleconn *lsc;
        char *rmsg = NULL;
        char *rmatch = NULL;
 
-       for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+       for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
                int err = LDAP_SUCCESS;
                char *msg = NULL;
                char *match = NULL;
 
-               ldap_get_option( lsc[ 0 ]->ld, LDAP_OPT_ERROR_NUMBER, &err );
+               ldap_get_option( lsc->ld, LDAP_OPT_ERROR_NUMBER, &err );
                if ( err != LDAP_SUCCESS ) {
                        /*
                         * better check the type of error. In some cases
@@ -416,9 +415,9 @@ meta_back_op_result( struct metaconn *lc, Operation *op )
                         * success if at least one of the targets gave
                         * positive result ...
                         */
-                       ldap_get_option( lsc[ 0 ]->ld,
+                       ldap_get_option( lsc->ld,
                                        LDAP_OPT_ERROR_STRING, &msg );
-                       ldap_get_option( lsc[ 0 ]->ld,
+                       ldap_get_option( lsc->ld,
                                        LDAP_OPT_MATCHED_DN, &match );
                        err = ldap_back_map_result( err );
 
diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c
new file mode 100644 (file)
index 0000000..643f78b
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ *
+ * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
+ *
+ * This work has been developed to fulfill the requirements
+ * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
+ * to the OpenLDAP Foundation in the hope that it may be useful
+ * to the Open Source community, but WITHOUT ANY WARRANTY.
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author and SysNet s.n.c. are not responsible for the consequences
+ *    of use of this software, no matter how awful, even if they arise from 
+ *    flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ *    explicit claim or by omission.  Since few users ever read sources,
+ *    credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.  Since few users
+ *    ever read sources, credits should appear in the documentation.
+ *    SysNet s.n.c. cannot be responsible for the consequences of the
+ *    alterations.
+ *
+ * 4. This notice may not be removed or altered.
+ *
+ *
+ * This software is based on the backend back-ldap, implemented
+ * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
+ * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
+ * contributors. The contribution of the original software to the present
+ * implementation is acknowledged in this copyright statement.
+ *
+ * A special acknowledgement goes to Howard for the overall architecture
+ * (and for borrowing large pieces of code), and to Mark, who implemented
+ * from scratch the attribute/objectclass mapping.
+ *
+ * The original copyright statement follows.
+ *
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ *    software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ *    explicit claim or by omission.  Since few users ever read sources,
+ *    credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.  Since few users
+ *    ever read sources, credits should appear in the
+ *    documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ *                
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "../back-ldap/back-ldap.h"
+#include "back-meta.h"
+
+/*
+ * The meta-directory has one suffix, called <suffix>.
+ * It handles a pool of target servers, each with a branch suffix
+ * of the form <branch X>,<suffix>
+ *
+ * When the meta-directory receives a request with a dn that belongs
+ * to a branch, the corresponding target is invoked. When the dn
+ * does not belong to a specific branch, all the targets that
+ * are compatible with the dn are selected as candidates, and
+ * the request is spawned to all the candidate targets
+ *
+ * A request is characterized by a dn. The following cases are handled:
+ *     - the dn is the suffix: <dn> == <suffix>,
+ *             all the targets are candidates (search ...)
+ *     - the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
+ *     - the dn is a subtree of a branch suffix:
+ *             <dn> == <rdn>,<branch X>,<suffix>,
+ *             the target is the only candidate.
+ *
+ * A possible extension will include the handling of multiple suffixes
+ */
+
+/*
+ * returns 1 if suffix is candidate for dn, otherwise 0
+ *
+ * Note: this function should never be called if dn is the <suffix>.
+ */
+int 
+meta_back_is_candidate(
+               struct berval   *nsuffix,
+               struct berval   *ndn
+)
+{
+       if ( dnIsSuffix( nsuffix, ndn ) || dnIsSuffix( ndn, nsuffix ) ) {
+               /*
+                * suffix longer than dn
+                */
+               return META_CANDIDATE;
+       }
+
+       return META_NOT_CANDIDATE;
+}
+
+/*
+ * meta_back_count_candidates
+ *
+ * returns a count of the possible candidate targets
+ * Note: dn MUST be normalized
+ */
+
+int
+meta_back_count_candidates(
+               struct metainfo         *li,
+               struct berval           *ndn
+)
+{
+       int i, cnt = 0;
+
+       /*
+        * I know assertions should not check run-time values;
+        * at present I didn't find a place for such checks
+        * after config.c
+        */
+       assert( li->targets != NULL );
+       assert( li->ntargets != 0 );
+
+       for ( i = 0; i < li->ntargets; ++i ) {
+               if ( meta_back_is_candidate( &li->targets[ i ]->suffix, ndn ) ) {
+                       ++cnt;
+               }
+       }
+
+       return cnt;
+}
+
+/*
+ * meta_back_is_candidate_unique
+ *
+ * checks whether a candidate is unique
+ * Note: dn MUST be normalized
+ */
+int
+meta_back_is_candidate_unique(
+               struct metainfo         *li,
+               struct berval           *ndn
+)
+{
+       return ( meta_back_count_candidates( li, ndn ) == 1 );
+}
+
+/*
+ * meta_back_select_unique_candidate
+ *
+ * returns the index of the candidate in case it is unique, otherwise -1
+ * Note: dn MUST be normalized.
+ * Note: if defined, the default candidate is returned in case of no match.
+ */
+int
+meta_back_select_unique_candidate(
+               struct metainfo         *li,
+               struct berval           *ndn
+)
+{
+       int i;
+       
+       switch ( meta_back_count_candidates( li, ndn ) ) {
+       case 1:
+               break;
+       case 0:
+       default:
+               return ( li->defaulttarget == META_DEFAULT_TARGET_NONE
+                               ? -1 : li->defaulttarget );
+       }
+
+       for ( i = 0; i < li->ntargets; ++i ) {
+               if ( meta_back_is_candidate( &li->targets[ i ]->suffix, ndn ) ) {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+/*
+ * meta_clear_unused_candidates
+ *
+ * clears all candidates except candidate
+ */
+int
+meta_clear_unused_candidates(
+               struct metainfo         *li,
+               struct metaconn         *lc,
+               int                     candidate,
+               int                     reallyclean
+)
+{
+       int i;
+       
+       for ( i = 0; i < li->ntargets; ++i ) {
+               if ( i == candidate ) {
+                       continue;
+               }
+               meta_clear_one_candidate( &lc->conns[ i ], reallyclean );
+       }
+
+       return 0;
+}
+
+/*
+ * meta_clear_one_candidate
+ *
+ * clears the selected candidate
+ */
+int
+meta_clear_one_candidate(
+               struct metasingleconn   *lsc,
+               int                     reallyclean
+)
+{
+       lsc->candidate = META_NOT_CANDIDATE;
+
+       if ( !reallyclean ) {
+               return 0;
+       }
+
+       if ( lsc->ld ) {
+               ldap_unbind( lsc->ld );
+               lsc->ld = NULL;
+       }
+
+       if ( lsc->bound_dn.bv_val != NULL ) {
+               ber_memfree( lsc->bound_dn.bv_val );
+               lsc->bound_dn.bv_val = NULL;
+               lsc->bound_dn.bv_len = 0;
+       }
+
+       return 0;
+}
+
index fea4dcf9d28b76d03b20d4f64ee0902ad9163f4e..71475fdc39214ac2875598f4f1201cf1949d13e1 100644 (file)
@@ -87,7 +87,7 @@ meta_back_compare(
 {
        struct metainfo *li = ( struct metainfo * )be->be_private;
        struct metaconn *lc;
-       struct metasingleconn **lsc;
+       struct metasingleconn *lsc;
        char *match = NULL, *err = NULL, *mmatch = NULL;
        int candidates = 0, last = 0, i, count, rc;
                int cres = LDAP_SUCCESS, rres = LDAP_SUCCESS;
@@ -107,12 +107,12 @@ meta_back_compare(
        /*
         * start an asynchronous compare for each candidate target
         */
-       for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+       for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
                char *mdn = NULL;
                struct berval mapped_attr = ava->aa_desc->ad_cname;
                struct berval mapped_value = ava->aa_value;
 
-               if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+               if ( lsc->candidate != META_CANDIDATE ) {
                        continue;
                }
 
@@ -158,7 +158,7 @@ meta_back_compare(
                                        &ava->aa_value, &mapped_value, 0 );
 
                        if ( mapped_value.bv_val == NULL ) {
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                continue;
                        }
                /*
@@ -168,7 +168,7 @@ meta_back_compare(
                        ldap_back_map( &li->targets[ i ]->at_map,
                                &ava->aa_desc->ad_cname, &mapped_attr, 0 );
                        if ( mapped_attr.bv_val == NULL ) {
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                continue;
                        }
                }
@@ -178,10 +178,10 @@ meta_back_compare(
                 * that returns determines the result; a constraint on unicity
                 * of the result ought to be enforced
                 */
-               msgid[ i ] = ldap_compare( lc->conns[ i ]->ld, mdn,
+               msgid[ i ] = ldap_compare( lc->conns[ i ].ld, mdn,
                                mapped_attr.bv_val, mapped_value.bv_val );
                if ( msgid[ i ] == -1 ) {
-                       lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                       lsc->candidate = META_NOT_CANDIDATE;
                        continue;
                }
 
@@ -206,15 +206,15 @@ meta_back_compare(
                /*
                 * FIXME: should we check for abandon?
                 */
-               for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; lsc++, i++ ) {
+               for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
                        int lrc;
                        LDAPMessage *res = NULL;
 
-                       if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+                       if ( lsc->candidate != META_CANDIDATE ) {
                                continue;
                        }
 
-                       lrc = ldap_result( lsc[ 0 ]->ld, msgid[ i ],
+                       lrc = ldap_result( lsc->ld, msgid[ i ],
                                        0, NULL, &res );
 
                        if ( lrc == 0 ) {
@@ -232,8 +232,7 @@ meta_back_compare(
                                        goto finish;
                                }
                                
-                               cres = ldap_result2error( lsc[ 0 ]->ld,
-                                               res, 1 );
+                               cres = ldap_result2error( lsc->ld, res, 1 );
                                switch ( cres ) {
                                case LDAP_COMPARE_TRUE:
                                case LDAP_COMPARE_FALSE:
@@ -256,22 +255,22 @@ meta_back_compare(
                                        if ( err != NULL ) {
                                                free( err );
                                        }
-                                       ldap_get_option( lsc[ 0 ]->ld,
+                                       ldap_get_option( lsc->ld,
                                                LDAP_OPT_ERROR_STRING, &err );
 
                                        if ( match != NULL ) {
                                                free( match );
                                        }
-                                       ldap_get_option( lsc[ 0 ]->ld,
+                                       ldap_get_option( lsc->ld,
                                                LDAP_OPT_MATCHED_DN, &match );
                                        
                                        last = i;
                                        break;
                                }
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                --candidates;
                        } else {
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                --candidates;
                                if ( res ) {
                                        ldap_msgfree( res );
index 7eeba8597236b5c98c9a33f81455cc19f71306b4..249555836e04d23608fc19c6220b11759d4bf8a0 100644 (file)
@@ -170,7 +170,6 @@ static struct metaconn *
 metaconn_alloc( int ntargets )
 {
        struct metaconn *lc;
-       int i;
 
        assert( ntargets > 0 );
 
@@ -182,22 +181,12 @@ metaconn_alloc( int ntargets )
        /*
         * make it a null-terminated array ...
         */
-       lc->conns = ch_calloc( sizeof( struct metasingleconn ), ntargets+1 );
+       lc->conns = ch_calloc( sizeof( struct metasingleconn ), ntargets+1 );
        if ( lc->conns == NULL ) {
                free( lc );
                return NULL;
        }
-
-       for ( i = 0; i < ntargets; i++ ) {
-               lc->conns[ i ] =
-                       ch_calloc( sizeof( struct metasingleconn ), 1 );
-               if ( lc->conns[ i ] == NULL ) {
-                       charray_free( ( char ** )lc->conns );
-                       free( lc->conns );
-                       free( lc );
-                       return NULL;
-               }
-       }
+       lc->conns[ ntargets ].candidate = META_LAST_CONN;
 
        lc->bound_target = META_BOUND_NONE;
 
@@ -219,12 +208,7 @@ metaconn_free(
        }
        
        if ( lc->conns ) {
-               int i;
-
-               for ( i = 0; lc->conns[ i ] != NULL; ++i ) {
-                       free( lc->conns[ i ] );
-               }
-               charray_free( ( char ** )lc->conns );
+               ch_free( lc->conns );
        }
 
        free( lc );
@@ -422,7 +406,7 @@ meta_back_getconn(
                 * sends the appropriate result.
                 */
                err = init_one_conn( conn, op, li->targets[ i ],
-                               vers, lc->conns[ i ] );
+                               vers, &lc->conns[ i ] );
                if ( err != LDAP_SUCCESS ) {
                
                        /*
@@ -430,7 +414,7 @@ meta_back_getconn(
                         * be init'd, should the other ones
                         * be tried?
                         */
-                       ( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+                       ( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
                        if ( new_conn ) {
                                metaconn_free( lc );
                        }
@@ -452,7 +436,7 @@ meta_back_getconn(
                         * also init'd
                         */
                        int lerr = init_one_conn( conn, op, li->targets[ i ],
-                                       vers, lc->conns[ i ] );
+                                       vers, &lc->conns[ i ] );
                        if ( lerr != LDAP_SUCCESS ) {
                                
                                /*
@@ -460,7 +444,7 @@ meta_back_getconn(
                                 * be init'd, should the other ones
                                 * be tried?
                                 */
-                               ( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+                               ( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
                                err = lerr;
                                continue;
                        }
@@ -480,7 +464,7 @@ meta_back_getconn(
                                 */
                                int lerr = init_one_conn( conn, op,
                                                li->targets[ i ],
-                                               vers, lc->conns[ i ] );
+                                               vers, &lc->conns[ i ] );
                                if ( lerr != LDAP_SUCCESS ) {
                                
                                        /*
@@ -488,7 +472,7 @@ meta_back_getconn(
                                         * be init'd, should the other ones
                                         * be tried?
                                         */
-                                       ( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+                                       ( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
                                        err = lerr;
                                        continue;
                                }
index ce268732ed69a4fb529bca67a2a8476f5ea34e8d..daeada0ad30d0d17507c34041092f458953538d0 100644 (file)
@@ -127,7 +127,7 @@ meta_back_delete(
                return -1;
        }
        
-       ldap_delete_s( lc->conns[ candidate ]->ld, mdn );
+       ldap_delete_s( lc->conns[ candidate ].ld, mdn );
 
        if ( mdn != dn->bv_val ) {
                free( mdn );
index 67886898a3236262b2767914b2d6d7407327fc51..b482847d6a18f7370b3e30f7303a2d33e4305898 100644 (file)
@@ -74,6 +74,7 @@
 #include "slap.h"
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
+#include "lutil.h"
 
 /* return 0 IFF op_dn is a value in group_at (member) attribute
  * of entry with gr_dn AND that entry has an objectClass
index 3f9a9f89642862b6c13716615732db3a3d8cdfab..3ca62e4d52f1ce1bb8264c7d4f28ce535db4a980 100644 (file)
@@ -158,16 +158,16 @@ conn_free(
        struct metaconn *lc
 )
 {
-       struct metasingleconn **lsc;
+       struct metasingleconn *lsc;
 
-       for ( lsc = lc->conns; lsc[ 0 ] != NULL; lsc++ ) {
-               if ( lsc[ 0 ]->ld != NULL ) {
-                       ldap_unbind( lsc[ 0 ]->ld );
+       for ( lsc = lc->conns; !META_LAST(lsc); lsc++ ) {
+               if ( lsc->ld != NULL ) {
+                       ldap_unbind( lsc->ld );
                }
-               if ( lsc[ 0 ]->bound_dn.bv_val ) {
-                       ber_memfree( lsc[ 0 ]->bound_dn.bv_val );
+               if ( lsc->bound_dn.bv_val ) {
+                       ber_memfree( lsc->bound_dn.bv_val );
                }
-               free( lsc[ 0 ] );
+               free( lsc );
        }
        free( lc->conns );
        free( lc );
index 24013e8a8f5682dd8b3f0e5dfb6a78aa4a7ddd36..45429332c4bb8f233f0321d201b305607b3c0d14 100644 (file)
@@ -200,7 +200,7 @@ meta_back_modify(
        }
        modv[ i ] = 0;
 
-       ldap_modify_s( lc->conns[ candidate ]->ld, mdn, modv );
+       ldap_modify_s( lc->conns[ candidate ].ld, mdn, modv );
 
        if ( mdn != dn->bv_val ) {
                free( mdn );
index 0f05e4f713a084f1bef9dab461f8c8c61f2c713e..c0f6d1437ff666c9359658cda0cd406afb8d9125 100644 (file)
@@ -127,7 +127,7 @@ meta_back_modrdn(
                        return -1;
                }
 
-               ldap_set_option( lc->conns[ nsCandidate ]->ld,
+               ldap_set_option( lc->conns[ nsCandidate ].ld,
                                LDAP_OPT_PROTOCOL_VERSION, &version );
                
                /*
@@ -194,7 +194,7 @@ meta_back_modrdn(
                return -1;
        }
 
-       ldap_rename2_s( lc->conns[ candidate ]->ld, mdn, newrdn->bv_val,
+       ldap_rename2_s( lc->conns[ candidate ].ld, mdn, newrdn->bv_val,
                        mnewSuperior, deleteoldrdn );
 
        if ( mdn != dn->bv_val ) {
index 811a51ee42789947de09d03f0144dea7c3135cd1..7d8fc6b7f806136ccd7c24da28b66d95d350cd7e 100644 (file)
@@ -116,7 +116,7 @@ meta_back_search(
 {
        struct metainfo *li = ( struct metainfo * )be->be_private;
        struct metaconn *lc;
-       struct metasingleconn **lsc;
+       struct metasingleconn *lsc;
        struct timeval  tv;
        LDAPMessage     *res, *e;
        int     count, rc = 0, *msgid, sres = LDAP_NO_SUCH_OBJECT;
@@ -195,26 +195,26 @@ meta_back_search(
        /*
         * Inits searches
         */
-       for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+       for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
                char    *realbase = ( char * )base->bv_val;
                int     realscope = scope;
                ber_len_t suffixlen;
                char    *mapped_filter, **mapped_attrs;
                
-               if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+               if ( lsc->candidate != META_CANDIDATE ) {
                        continue;
                }
 
                if ( deref != -1 ) {
-                       ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_DEREF,
+                       ldap_set_option( lsc->ld, LDAP_OPT_DEREF,
                                        ( void * )&deref);
                }
                if ( tlimit != -1 ) {
-                       ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_TIMELIMIT,
+                       ldap_set_option( lsc->ld, LDAP_OPT_TIMELIMIT,
                                        ( void * )&tlimit);
                }
                if ( slimit != -1 ) {
-                       ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_SIZELIMIT,
+                       ldap_set_option( lsc->ld, LDAP_OPT_SIZELIMIT,
                                        ( void * )&slimit);
                }
 
@@ -238,7 +238,7 @@ meta_back_search(
                                        /*
                                         * this target is no longer candidate
                                         */
-                                       lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                                       lsc->candidate = META_NOT_CANDIDATE;
                                        continue;
                                }
                                break;
@@ -261,7 +261,7 @@ meta_back_search(
                                /*
                                 * this target is no longer candidate
                                 */
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                continue;
                        }
 
@@ -372,10 +372,10 @@ meta_back_search(
                /*
                 * Starts the search
                 */
-               msgid[ i ] = ldap_search( lsc[ 0 ]->ld, mbase, realscope,
+               msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
                                mapped_filter, mapped_attrs, attrsonly ); 
                if ( msgid[ i ] == -1 ) {
-                       lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                       lsc->candidate = META_NOT_CANDIDATE;
                        continue;
                }
 
@@ -410,13 +410,13 @@ meta_back_search(
                /* check for abandon */
                ab = op->o_abandon;
 
-               for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; lsc++, i++ ) {
-                       if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+               for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
+                       if ( lsc->candidate != META_CANDIDATE ) {
                                continue;
                        }
                        
                        if ( ab ) {
-                               ldap_abandon( lsc[ 0 ]->ld, msgid[ i ] );
+                               ldap_abandon( lsc->ld, msgid[ i ] );
                                rc = 0;
                                break;
                        }
@@ -428,7 +428,7 @@ meta_back_search(
                                goto finish;
                        }
 
-                       rc = ldap_result( lsc[ 0 ]->ld, msgid[ i ],
+                       rc = ldap_result( lsc->ld, msgid[ i ],
                                        0, &tv, &res );
 
                        if ( rc == 0 ) {
@@ -444,25 +444,25 @@ meta_back_search(
                                /* anything else needs be done? */
                                goto finish;
                        } else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
-                               e = ldap_first_entry( lsc[ 0 ]->ld, res );
+                               e = ldap_first_entry( lsc->ld, res );
                                meta_send_entry(be, op, lc, i, e, attrs,
                                                attrsonly);
                                count++;
                                ldap_msgfree( res );
                                gotit = 1;
                        } else {
-                               sres = ldap_result2error( lsc[ 0 ]->ld,
+                               sres = ldap_result2error( lsc->ld,
                                                res, 1 );
                                sres = ldap_back_map_result( sres );
                                if ( err != NULL ) {
                                        free( err );
                                }
-                               ldap_get_option( lsc[ 0 ]->ld,
+                               ldap_get_option( lsc->ld,
                                                LDAP_OPT_ERROR_STRING, &err );
                                if ( match != NULL ) {
                                        free( match );
                                }
-                               ldap_get_option( lsc[ 0 ]->ld,
+                               ldap_get_option( lsc->ld,
                                                LDAP_OPT_MATCHED_DN, &match );
 
 #ifdef NEW_LOGGING
@@ -482,7 +482,7 @@ meta_back_search(
                                 * When no candidates are left,
                                 * the outer cycle finishes
                                 */
-                               lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+                               lsc->candidate = META_NOT_CANDIDATE;
                                --candidates;
                        }
                }
index 84b36adb21fa555aa7c3fdc47ecbb1231c5c8890..e4f381e988d376874aac7187314666066e45a1b0 100644 (file)
@@ -117,14 +117,12 @@ meta_back_conn_destroy(
                 * Cleanup rewrite session
                 */
                for ( i = 0; i < li->ntargets; ++i ) {
-                       if ( lc->conns[ i ]->ld == NULL ) {
-                               free( lc->conns[ i ] );
+                       if ( lc->conns[ i ].ld == NULL ) {
                                continue;
                        }
 
                        rewrite_session_delete( li->targets[ i ]->rwinfo, conn );
-                       meta_clear_one_candidate( lc->conns[ i ], 1 );
-                       free( lc->conns[ i ] );
+                       meta_clear_one_candidate( &lc->conns[ i ], 1 );
                }
 
                free( lc->conns );
index ad7ab23240e57b82b44f23f385c842e8705caad2..070f8524f9927444ddf5b6b68770355694e3b394 100644 (file)
@@ -34,6 +34,7 @@
 #include "portable.h"
 
 #include <stdio.h>
+#include "lutil.h"
 
 #include "slap.h"
 #include "back-monitor.h"