]> git.sur5r.net Git - openldap/commitdiff
Rough in extended ops, modify, and modrdn.
authorKurt Zeilenga <kurt@openldap.org>
Wed, 27 Sep 2000 22:28:59 +0000 (22:28 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 27 Sep 2000 22:28:59 +0000 (22:28 +0000)
General code cleanup.

20 files changed:
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/backbdb.dsp
servers/slapd/back-bdb/bind.c
servers/slapd/back-bdb/compare.c
servers/slapd/back-bdb/config.c
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/dn2entry.c
servers/slapd/back-bdb/dn2id.c
servers/slapd/back-bdb/extended.c [new file with mode: 0644]
servers/slapd/back-bdb/external.h
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/idl.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/modify.c [new file with mode: 0644]
servers/slapd/back-bdb/modrdn.c [new file with mode: 0644]
servers/slapd/back-bdb/passwd.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/referral.c
servers/slapd/back-bdb/search.c

index 0fbb162387903d08ae2abcea985f7b311a66148d..8fbef95a974bdf3641cd8c3324ab1f9f568c41f5 100644 (file)
@@ -27,6 +27,7 @@ bdb_add(
        const char      *text = NULL;
        AttributeDescription *children = slap_schema.si_ad_children;
        DB_TXN          *ltid = NULL;
+       struct bdb_op_info opinfo;
 
        Debug(LDAP_DEBUG_ARGS, "==> bdb_add: %s\n", e->e_dn, 0, 0);
 
@@ -76,7 +77,10 @@ retry:       rc = txn_abort( ltid );
                goto return_results;
        }
 
-       op->o_private = ltid;
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
        
        /*
         * Get the parent dn and see if the corresponding entry exists.
@@ -88,8 +92,8 @@ retry:        rc = txn_abort( ltid );
        if( pdn != NULL && *pdn != '\0' ) {
                Entry *matched = NULL;
 
-               /* get parent with reader lock */
-               rc = dn2entry_r( be, ltid, pdn, &p, &matched );
+               /* get parent */
+               rc = bdb_dn2entry( be, ltid, pdn, &p, &matched, 0 );
                ch_free( pdn );
 
                switch( rc ) {
@@ -125,7 +129,7 @@ retry:      rc = txn_abort( ltid );
                                0, 0, 0 );
 
                        send_ldap_result( conn, op, rc = LDAP_REFERRAL,
-                           matched_dn, NULL, refs, NULL );
+                               matched_dn, NULL, refs, NULL );
 
                        if( matched != NULL ) {
                                ber_bvecfree( refs );
@@ -165,7 +169,7 @@ retry:      rc = txn_abort( ltid );
                                0, 0, 0 );
 
                        send_ldap_result( conn, op, rc = LDAP_REFERRAL,
-                           matched_dn, NULL, refs, NULL );
+                               matched_dn, NULL, refs, NULL );
 
                        ber_bvecfree( refs );
                        free( matched_dn );
index c9fa58d905d3e358d0072477c696a524a19efaa7..dee9b15684b3d1089d2436696788e3f6911cc3a7 100644 (file)
@@ -74,6 +74,12 @@ struct bdb_info {
 #define bi_id2entry    bi_databases[BDB_ID2ENTRY]
 #define bi_dn2id       bi_databases[BDB_DN2ID]
 
+struct bdb_op_info {
+       BackendDB*      boi_bdb;
+       DB_TXN*         boi_txn;
+       int                     boi_err;
+};
+
 LDAP_END_DECL
 
 #include "proto-bdb.h"
index 49b043fc9d210a3d082c938248489b8d94c92df1..e31cc1a7861fd647166e87daa35bd0dce7606588 100644 (file)
@@ -163,6 +163,10 @@ SOURCE=.\error.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\extended.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\external.h
 # End Source File
 # Begin Source File
@@ -179,10 +183,22 @@ SOURCE=.\init.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\modify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modrdn.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\nextid.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\passwd.c
+# End Source File
+# Begin Source File
+
 SOURCE=".\proto-bdb.h"
 # End Source File
 # Begin Source File
index da28294b7d80b7bc2bb49581469e10d505cdd98d..bd9a8bf58f01d174e680009d731135a931aeda97 100644 (file)
 
 int
 bdb_bind(
-    Backend            *be,
-    Connection         *conn,
-    Operation          *op,
-    const char         *dn,
-    const char         *ndn,
-    int                        method,
-    struct berval      *cred,
+       Backend         *be,
+       Connection              *conn,
+       Operation               *op,
+       const char              *dn,
+       const char              *ndn,
+       int                     method,
+       struct berval   *cred,
        char**  edn
 )
 {
@@ -44,8 +44,8 @@ bdb_bind(
 
        *edn = NULL;
 
-       /* fetch entry */
-       rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+       /* get entry */
+       rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -53,7 +53,7 @@ bdb_bind(
                break;
        default:
                send_ldap_result( conn, op, rc=LDAP_OTHER,
-                   NULL, "internal error", NULL, NULL );
+                       NULL, "internal error", NULL, NULL );
                return rc;
        }
 
@@ -114,10 +114,10 @@ bdb_bind(
        if ( is_entry_alias( e ) ) {
                /* entry is an alias, don't allow bind */
                Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
-                   0, 0 );
+                       0, 0 );
 
                send_ldap_result( conn, op, rc = LDAP_ALIAS_PROBLEM,
-                   NULL, "entry is alias", NULL, NULL );
+                       NULL, "entry is alias", NULL, NULL );
 
                goto done;
        }
@@ -128,7 +128,7 @@ bdb_bind(
                        conn, op, e );
 
                Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
-                   0, 0 );
+                       0, 0 );
 
                if( refs != NULL ) {
                        send_ldap_result( conn, op, rc = LDAP_REFERRAL,
@@ -165,7 +165,7 @@ bdb_bind(
 
                if ( (a = attr_find( e->e_attrs, password )) == NULL ) {
                        send_ldap_result( conn, op, rc = LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL, NULL, NULL );
+                               NULL, NULL, NULL, NULL );
                        goto done;
                }
 
@@ -182,7 +182,7 @@ bdb_bind(
        case LDAP_AUTH_KRBV41:
                if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
                        send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
-                           NULL, NULL, NULL, NULL );
+                               NULL, NULL, NULL, NULL );
                        goto done;
                }
 
@@ -195,7 +195,7 @@ bdb_bind(
                }
 
                sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
-                   : "", ad.pinst, ad.prealm );
+                       : "", ad.pinst, ad.prealm );
 
                if ( (a = attr_find( e->e_attrs, krbattr )) == NULL ) {
                        /*
@@ -206,7 +206,7 @@ bdb_bind(
                                break;
                        }
                        send_ldap_result( conn, op, rc = LDAP_INAPPROPRIATE_AUTH,
-                           NULL, NULL, NULL, NULL );
+                               NULL, NULL, NULL, NULL );
                        goto done;
 
                } else {        /* look for krbname match */
@@ -217,7 +217,7 @@ bdb_bind(
 
                        if ( value_find( a->a_desc, a->a_vals, &krbval ) != 0 ) {
                                send_ldap_result( conn, op,
-                                   rc = LDAP_INVALID_CREDENTIALS,
+                                       rc = LDAP_INVALID_CREDENTIALS,
                                        NULL, NULL, NULL, NULL );
                                goto done;
                        }
@@ -234,7 +234,7 @@ bdb_bind(
 
        default:
                send_ldap_result( conn, op, rc = LDAP_STRONG_AUTH_NOT_SUPPORTED,
-                   NULL, "authentication method not supported", NULL, NULL );
+                       NULL, "authentication method not supported", NULL, NULL );
                goto done;
        }
 
index 98d95cdf5e332cd312889046685a2229d980cf97..2764cdf9e8d957b2dffb479b49f87172aec0cbaa 100644 (file)
 
 int
 bdb_compare(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    const char *dn,
-    const char *ndn,
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char      *dn,
+       const char      *ndn,
        AttributeAssertion *ava
 )
 {
@@ -32,7 +32,7 @@ bdb_compare(
        int             manageDSAit = get_manageDSAit( op );
 
        /* get entry */
-       rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+       rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
 
        switch( rc ) {
        case DB_NOTFOUND:
@@ -74,10 +74,10 @@ bdb_compare(
                        conn, op, e );
 
                Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
-                   0, 0 );
+                       0, 0 );
 
                send_ldap_result( conn, op, rc = LDAP_REFERRAL,
-                   e->e_dn, NULL, refs, NULL );
+                       e->e_dn, NULL, refs, NULL );
 
                ber_bvecfree( refs );
                goto done;
index c881bec9232b2d7bca8a7e0505cbddc8fe590c75..b1bf856a971b6b45449be221b9d1149bf0bb4db9 100644 (file)
 
 int
 bdb_db_config(
-    BackendDB  *be,
-    const char *fname,
-    int                lineno,
-    int                argc,
-    char       **argv )
+       BackendDB       *be,
+       const char      *fname,
+       int             lineno,
+       int             argc,
+       char    **argv )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
 
        if ( bdb == NULL ) {
                fprintf( stderr, "%s: line %d: "
                        "bdb database info is null!\n",
-                   fname, lineno );
+                       fname, lineno );
                return 1;
        }
 
@@ -34,7 +34,7 @@ bdb_db_config(
                if ( argc < 2 ) {
                        fprintf( stderr, "%s: line %d: "
                                "missing dir in \"directory <dir>\" line\n",
-                           fname, lineno );
+                               fname, lineno );
                        return 1;
                }
                if ( bdb->bi_dbenv_home ) {
@@ -47,7 +47,7 @@ bdb_db_config(
                if ( argc < 2 ) {
                        fprintf( stderr, "%s: line %d: "
                                "missing mode in \"mode <mode>\" line\n",
-                           fname, lineno );
+                               fname, lineno );
                        return 1;
                }
                bdb->bi_dbenv_mode = strtol( argv[1], NULL, 0 );
@@ -59,13 +59,13 @@ bdb_db_config(
                if ( argc < 2 ) {
                        fprintf( stderr, "%s: line %d: "
                                "missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
-                           fname, lineno );
+                               fname, lineno );
                        return 1;
                } else if ( argc > 3 ) {
                        fprintf( stderr, "%s: line %d: "
                                "extra junk after \"index <attr> [pres,eq,approx,sub]\" "
                                "line (ignored)\n",
-                           fname, lineno );
+                               fname, lineno );
                }
                rc = attr_index_config( li, fname, lineno, argc - 1, &argv[1] );
 
@@ -76,7 +76,7 @@ bdb_db_config(
        } else {
                fprintf( stderr, "%s: line %d: "
                        "unknown directive \"%s\" in bdb database definition (ignored)\n",
-                   fname, lineno, argv[0] );
+                       fname, lineno, argv[0] );
        }
 
        return 0;
index 0b66029b579ccbd4edfad77a86e1736361c400eb..2c9bf2af0c2960a2c9242bc722fab5d50e37e6a1 100644 (file)
 
 int
 bdb_delete(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    const char *dn,
-    const char *ndn
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char      *dn,
+       const char      *ndn
 )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
@@ -31,6 +31,7 @@ bdb_delete(
        int             manageDSAit = get_manageDSAit( op );
        AttributeDescription *children = slap_schema.si_ad_children;
        DB_TXN          *ltid = NULL;
+       struct bdb_op_info opinfo;
 
        Debug(LDAP_DEBUG_ARGS, "==> bdb_delete: %s\n", dn, 0, 0);
 
@@ -57,13 +58,62 @@ retry:      rc = txn_abort( ltid );
                goto return_results;
        }
 
-       op->o_private = ltid;
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
 
-       pdn = dn_parent( be, e->e_ndn );
+       /* get entry for read/modify/write */
+       rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, DB_RMW );
+
+       switch( rc ) {
+       case 0:
+       case DB_NOTFOUND:
+               break;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto retry;
+       default:
+               rc = LDAP_OTHER;
+               text = "internal error";
+               goto return_results;
+       }
+
+       if ( e == NULL ) {
+               char *matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               Debug( LDAP_DEBUG_ARGS,
+                       "<=- bdb_delete: no such object %s\n",
+                       dn, 0, 0);
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb_entry_return( be, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if ( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               rc = -1;
+               goto done;
+       }
+
+       pdn = dn_parent( be, ndn );
 
        if( pdn != NULL && *pdn != '\0' ) {
-               /* get parent with reader lock */
-               rc = dn2entry_r( be, ltid, pdn, &p, NULL );
+               /* get parent */
+               rc = bdb_dn2entry( be, ltid, pdn, &p, NULL, 0 );
 
                ch_free( pdn );
 
@@ -116,53 +166,7 @@ retry:     rc = txn_abort( ltid );
                }
        }
 
-       /* get entry */
-       rc = dn2entry_w( be, ltid, ndn, &e, &matched );
-
-       switch( rc ) {
-       case 0:
-       case DB_NOTFOUND:
-               break;
-       case DB_LOCK_DEADLOCK:
-       case DB_LOCK_NOTGRANTED:
-               goto retry;
-       default:
-               rc = LDAP_OTHER;
-               text = "internal error";
-               goto return_results;
-       }
-
-       if ( e == NULL ) {
-               char *matched_dn = NULL;
-               struct berval **refs = NULL;
-
-               Debug( LDAP_DEBUG_ARGS,
-                       "<=- bdb_delete: no such object %s\n",
-                       dn, 0, 0);
-
-               if ( matched != NULL ) {
-                       matched_dn = ch_strdup( matched->e_dn );
-                       refs = is_entry_referral( matched )
-                               ? get_entry_referrals( be, conn, op, matched )
-                               : NULL;
-                       bdb_entry_return( be, matched );
-               } else {
-                       refs = default_referral;
-               }
-
-               send_ldap_result( conn, op, LDAP_REFERRAL,
-                       matched_dn, NULL, refs, NULL );
-
-               if ( matched != NULL ) {
-                       ber_bvecfree( refs );
-                       free( matched_dn );
-               }
-
-               rc = -1;
-               goto done;
-       }
-
-    if ( !manageDSAit && is_entry_referral( e ) ) {
+       if ( !manageDSAit && is_entry_referral( e ) ) {
                /* parent is a referral, don't allow add */
                /* parent is an alias, don't allow add */
                struct berval **refs = get_entry_referrals( be,
@@ -173,7 +177,7 @@ retry:      rc = txn_abort( ltid );
                        0, 0, 0 );
 
                send_ldap_result( conn, op, LDAP_REFERRAL,
-                   e->e_dn, NULL, refs, NULL );
+                       e->e_dn, NULL, refs, NULL );
 
                ber_bvecfree( refs );
 
index c8a34fe55a3de41ae7f1d596887c6365afe75b9d..f0ba6c7731978710f7ef86081352ccae2169a787 100644 (file)
 
 int
 bdb_dn2entry(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *tid,
-    const char *dn,
+       const char *dn,
        Entry **e,
-    Entry **matched,
+       Entry **matched,
        int flags )
 {
        int rc;
index 2876f438f16e1b3773f90282829338751c66ea11..3479310f47b95abcb7d05c19be14535abb08ae01 100644 (file)
 
 int
 bdb_dn2id_add(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *txn,
-    const char *dn,
-    ID         id
+       const char      *dn,
+       ID              id
 )
 {
        int             rc;
@@ -102,10 +102,10 @@ done:
 
 int
 bdb_dn2id_delete(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *txn,
-    const char *dn,
-    ID         id )
+       const char      *dn,
+       ID              id )
 {
        int             rc;
        DBT             key;
@@ -185,9 +185,9 @@ done:
 
 int
 bdb_dn2id(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *txn,
-    const char *dn,
+       const char      *dn,
        ID *id )
 {
        int             rc;
@@ -221,9 +221,9 @@ bdb_dn2id(
 
 int
 bdb_dn2id_matched(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *txn,
-    const char *in,
+       const char      *in,
        ID *id,
        char **matchedDN )
 {
@@ -307,9 +307,9 @@ bdb_dn2id_matched(
 
 int
 bdb_dn2id_children(
-    BackendDB  *be,
+       BackendDB       *be,
        DB_TXN *txn,
-    const char *dn )
+       const char *dn )
 {
        int             rc;
        DBT             key, data;
diff --git a/servers/slapd/back-bdb/extended.c b/servers/slapd/back-bdb/extended.c
new file mode 100644 (file)
index 0000000..04b96f8
--- /dev/null
@@ -0,0 +1,52 @@
+/* extended.c - ldbm backend extended routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+struct exop {
+       char *oid;
+       SLAP_EXTENDED_FN        extended;
+} exop_table[] = {
+       { LDAP_EXOP_X_MODIFY_PASSWD, bdb_exop_passwd },
+       { NULL, NULL }
+};
+
+int
+bdb_extended(
+       Backend         *be,
+       Connection              *conn,
+       Operation               *op,
+       const char              *reqoid,
+       struct berval   *reqdata,
+       char            **rspoid,
+       struct berval   **rspdata,
+       LDAPControl *** rspctrls,
+       const char**    text,
+       struct berval *** refs 
+)
+{
+       int i;
+
+       for( i=0; exop_table[i].oid != NULL; i++ ) {
+               if( strcmp( exop_table[i].oid, reqoid ) == 0 ) {
+                       return (exop_table[i].extended)(
+                               be, conn, op,
+                               reqoid, reqdata,
+                               rspoid, rspdata, rspctrls,
+                               text, refs );
+               }
+       }
+
+       *text = "not supported within naming context";
+       return LDAP_OPERATIONS_ERROR;
+}
\ No newline at end of file
index db1ccac2c713e066c0cda9fcbcc5303b1c716b3c..0784a7cdd37a254202d2bca8cc0351c804f571ef 100644 (file)
@@ -56,11 +56,11 @@ extern int  bdb_unbind LDAP_P(( BackendDB *bd,
        Connection *conn, Operation *op ));
 
 extern int bdb_referrals(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    const char *dn,
-    const char *ndn,
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char *dn,
+       const char *ndn,
        const char **text );
 
 LDAP_END_DECL
index 8fbff048d490597407d9753ce1528d70f1ad9b68..51751c230cf41dc441a671241072761c405ac847 100644 (file)
@@ -41,6 +41,35 @@ int bdb_id2entry_add(
        return rc;
 }
 
+int bdb_id2entry_update(
+       BackendDB *be,
+       DB_TXN *tid,
+       Entry *e )
+{
+       struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+       DB *db = bdb->bi_id2entry->bdi_db;
+       DBT key, data;
+       struct berval *bv;
+       int rc;
+
+       DBTzero( &key );
+       key.data = (char *) &e->e_id;
+       key.size = sizeof(ID);
+
+       rc = entry_encode( e, &bv );
+       if( rc != LDAP_SUCCESS ) {
+               return -1;
+       }
+
+       DBTzero( &data );
+       bv2DBT( bv, &data );
+
+       rc = db->put( db, tid, &key, &data, 0 );
+
+       ber_bvfree( bv );
+       return rc;
+}
+
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
index 16146d12e5acb57fbd9ffaea31445615e7c4b935..acb67d6c52e44222c4d05d31db99995e6f0a9939 100644 (file)
@@ -128,11 +128,11 @@ static int idl_delete( ID *ids, ID id )
 
 int
 bdb_idl_insert_key(
-    BackendDB  *be,
-    DB                 *db,
+       BackendDB       *be,
+       DB                      *db,
        DB_TXN          *tid,
-    DBT                        *key,
-    ID                 id )
+       DBT                     *key,
+       ID                      id )
 {
        int     rc;
        ID ids[BDB_IDL_DB_SIZE];
@@ -216,11 +216,11 @@ bdb_idl_insert_key(
 
 int
 bdb_idl_delete_key(
-    BackendDB  *be,
-    DB                 *db,
+       BackendDB       *be,
+       DB                      *db,
        DB_TXN          *tid,
-    DBT                        *key,
-    ID                 id )
+       DBT                     *key,
+       ID                      id )
 {
        int     rc;
        ID ids[BDB_IDL_DB_SIZE];
index 632d601aa871ae204887277eb3c33f4d9d19ead4..77a48492802124b1b05227578d19d94831b973b0 100644 (file)
@@ -242,20 +242,20 @@ bdb_db_destroy( BackendDB *be )
 
 #ifdef SLAPD_BDB_DYNAMIC
 int back_bdb_LTX_init_module( int argc, char *argv[] ) {
-    BackendInfo bi;
+       BackendInfo bi;
 
-    memset( &bi, '\0', sizeof(bi) );
-    bi.bi_type = "bdb";
-    bi.bi_init = bdb_initialize;
+       memset( &bi, '\0', sizeof(bi) );
+       bi.bi_type = "bdb";
+       bi.bi_init = bdb_initialize;
 
-    backend_add( &bi );
-    return 0;
+       backend_add( &bi );
+       return 0;
 }
 #endif /* SLAPD_BDB_DYNAMIC */
 
 int
 bdb_initialize(
-    BackendInfo        *bi
+       BackendInfo     *bi
 )
 {
        static char *controls[] = {
@@ -305,12 +305,12 @@ bdb_initialize(
        bi->bi_op_bind = bdb_bind;
        bi->bi_op_compare = bdb_compare;
        bi->bi_op_delete = bdb_delete;
+       bi->bi_op_modify = bdb_modify;
+       bi->bi_op_modrdn = bdb_modrdn;
        bi->bi_op_search = bdb_search;
 
 #if 0
        bi->bi_op_unbind = bdb_unbind;
-       bi->bi_op_modify = bdb_modify;
-       bi->bi_op_modrdn = bdb_modrdn;
        bi->bi_op_abandon = bdb_abandon;
 
        bi->bi_extended = bdb_extended;
@@ -318,8 +318,8 @@ bdb_initialize(
        bi->bi_acl_group = bdb_group;
        bi->bi_acl_attribute = bdb_attribute;
 
-       bi->bi_chk_referrals = bdb_referrals;
 #endif
+       bi->bi_chk_referrals = bdb_referrals;
 
        bi->bi_entry_release_rw = 0;
 
diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c
new file mode 100644 (file)
index 0000000..46717f0
--- /dev/null
@@ -0,0 +1,497 @@
+/* modify.c - bdb backend modify routine */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+static int add_values( Entry *e, Modification *mod, char *dn );
+static int delete_values( Entry *e, Modification *mod, char *dn );
+static int replace_values( Entry *e, Modification *mod, char *dn );
+
+int bdb_modify_internal(
+       BackendDB *be,
+       Connection *conn,
+       Operation *op,
+       DB_TXN *tid,
+       const char *dn,
+       Modifications *modlist,
+       Entry *e,
+       const char **text )
+{
+       int rc, err;
+       Modification    *mod;
+       Modifications   *ml;
+       Attribute       *save_attrs;
+
+       Debug(LDAP_DEBUG_TRACE, "bdb_modify_internal: %s\n", dn, 0, 0);
+
+       if ( !acl_check_modlist( be, conn, op, e, modlist )) {
+               return LDAP_INSUFFICIENT_ACCESS;
+       }
+
+       save_attrs = e->e_attrs;
+       e->e_attrs = attrs_dup( e->e_attrs );
+
+       for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
+               mod = &ml->sml_mod;
+
+               switch ( mod->sm_op ) {
+               case LDAP_MOD_ADD:
+                       Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: add\n", 0, 0, 0);
+                       err = add_values( e, mod, op->o_ndn );
+
+                       if( err != LDAP_SUCCESS ) {
+                               Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+                                       err, *text, 0);
+                               *text = "modify: add values failed";
+                       }
+                       break;
+
+               case LDAP_MOD_DELETE:
+                       Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: delete\n", 0, 0, 0);
+                       err = delete_values( e, mod, op->o_ndn );
+                       assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
+                       if( err != LDAP_SUCCESS ) {
+                               Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+                                       err, *text, 0);
+                               *text = "modify: delete values failed";
+                       }
+                       break;
+
+               case LDAP_MOD_REPLACE:
+                       Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0);
+                       err = replace_values( e, mod, op->o_ndn );
+                       assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
+                       if( err != LDAP_SUCCESS ) {
+                               Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+                                       err, *text, 0);
+                               *text = "modify: replace values failed";
+                       }
+                       break;
+
+               case SLAP_MOD_SOFTADD:
+                       Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: softadd\n", 0, 0, 0);
+                       /* Avoid problems in index_add_mods()
+                        * We need to add index if necessary.
+                        */
+                       mod->sm_op = LDAP_MOD_ADD;
+                       err = add_values( e, mod, op->o_ndn );
+
+                       if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
+                               err = LDAP_SUCCESS;
+                       }
+
+                       if( err != LDAP_SUCCESS ) {
+                               Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+                                       err, *text, 0);
+                               *text = "modify: (soft)add values failed";
+                       }
+                       break;
+
+               default:
+                       Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
+                               mod->sm_op, 0, 0);
+                       *text = "Invalid modify operation";
+                       err = LDAP_OTHER;
+                       Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+                               err, *text, 0);
+               }
+
+               if ( err != LDAP_SUCCESS ) {
+                       attrs_free( e->e_attrs );
+                       e->e_attrs = save_attrs;
+                       /* unlock entry, delete from cache */
+                       return err; 
+               }
+       }
+
+       /* check that the entry still obeys the schema */
+       rc = entry_schema_check( e, save_attrs, text );
+       if ( rc != LDAP_SUCCESS ) {
+               attrs_free( e->e_attrs );
+               e->e_attrs = save_attrs;
+               Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
+                       *text, 0, 0 );
+               return rc;
+       }
+
+#if 0
+       /* delete indices for old attributes */
+       rc = index_entry_del( be, tid, e, save_attrs);
+
+       /* add indices for new attributes */
+       rc = index_entry_add( be, tid, e, e->e_attrs);
+#endif
+
+       attrs_free( save_attrs );
+
+       return rc;
+}
+
+
+int
+bdb_modify(
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char      *dn,
+       const char      *ndn,
+       Modifications   *modlist
+)
+{
+       struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+       int rc;
+       Entry           *matched;
+       Entry           *e;
+       int             manageDSAit = get_manageDSAit( op );
+       const char *text = NULL;
+       DB_TXN  *ltid;
+       struct bdb_op_info opinfo;
+
+       Debug(LDAP_DEBUG_ARGS, "bdb_back_modify: %s\n", dn, 0, 0);
+
+       if (0) {
+               /* transaction retry */
+retry: rc = txn_abort( ltid );
+               ltid = NULL;
+               op->o_private = NULL;
+               if( rc != 0 ) {
+                       rc = LDAP_OTHER;
+                       text = "internal error";
+                       goto return_results;
+               }
+       }
+
+       /* begin transaction */
+       rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: txn_begin failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               text = "internal error";
+               goto return_results;
+       }
+
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
+
+       /* get entry */
+       rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
+
+       if ( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: dn2entry failed (%d)\n",
+                       rc, 0, 0 );
+               switch( rc ) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               case DB_NOTFOUND:
+                       break;
+               default:
+                       rc = LDAP_OTHER;
+               }
+               text = "internal error";
+               goto return_results;
+       }
+
+       /* acquire and lock entry */
+       if ( e == NULL ) {
+               char* matched_dn = NULL;
+               struct berval **refs = NULL;
+
+               if ( matched != NULL ) {
+                       matched_dn = ch_strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb_entry_return( be, matched );
+
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if ( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               return rc;
+       }
+
+       if ( !manageDSAit && is_entry_referral( e ) ) {
+               /* parent is a referral, don't allow add */
+               /* parent is an alias, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: entry is referral\n",
+                       0, 0, 0 );
+
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+               goto done;
+       }
+       
+       /* Modify the entry */
+       rc = bdb_modify_internal( be, conn, op, ltid, ndn, modlist, e, &text );
+
+       if( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: modify failed (%d)\n",
+                       rc, 0, 0 );
+               switch( rc ) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               }
+               goto return_results;
+       }
+
+       /* change the entry itself */
+       rc = bdb_id2entry_update( be, ltid, e );
+       if ( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: id2entry update failed (%d)\n",
+                       rc, 0, 0 );
+               switch( rc ) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               }
+               text = "entry update failed";
+               goto return_results;
+       }
+
+       rc = txn_commit( ltid, 0 );
+       ltid = NULL;
+       op->o_private = NULL;
+
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: txn_commit failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               text = "commit failed";
+       } else {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify: added id=%08x dn=\"%s\"\n",
+                       e->e_id, e->e_dn, 0 );
+               rc = LDAP_SUCCESS;
+               text = NULL;
+       }
+
+return_results:
+       send_ldap_result( conn, op, rc,
+               NULL, text, NULL, NULL );
+
+done:
+       if( ltid != NULL ) {
+               txn_abort( ltid );
+               op->o_private = NULL;
+       }
+
+       bdb_entry_return( be, e );
+       return rc;
+}
+
+static int
+add_values(
+       Entry   *e,
+       Modification    *mod,
+       char    *dn
+)
+{
+       int             i;
+       Attribute       *a;
+
+       /* char *desc = mod->sm_desc->ad_cname->bv_val; */
+       MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
+
+       a = attr_find( e->e_attrs, mod->sm_desc );
+
+       /* check if the values we're adding already exist */
+       if ( a != NULL ) {
+               if( mr == NULL || !mr->smr_match ) {
+                       /* do not allow add of additional attribute
+                               if no equality rule exists */
+                       return LDAP_INAPPROPRIATE_MATCHING;
+               }
+
+               for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+                       int rc;
+                       int j;
+                       const char *text = NULL;
+                       struct berval *asserted;
+
+                       rc = value_normalize( mod->sm_desc,
+                               SLAP_MR_EQUALITY,
+                               mod->sm_bvalues[i],
+                               &asserted,
+                               &text );
+
+                       if( rc != LDAP_SUCCESS ) return rc;
+
+                       for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+                               int match;
+                               int rc = value_match( &match, mod->sm_desc, mr,
+                                       SLAP_MR_MODIFY_MATCHING,
+                                       a->a_vals[j], asserted, &text );
+
+                               if( rc == LDAP_SUCCESS && match == 0 ) {
+                                       ber_bvfree( asserted );
+                                       return LDAP_TYPE_OR_VALUE_EXISTS;
+                               }
+                       }
+
+                       ber_bvfree( asserted );
+               }
+       }
+
+       /* no - add them */
+       if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
+               /* this should return result return of attr_merge */
+               return LDAP_OTHER;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int
+delete_values(
+       Entry   *e,
+       Modification    *mod,
+       char    *dn
+)
+{
+       int             i, j, k, found;
+       Attribute       *a;
+       char *desc = mod->sm_desc->ad_cname->bv_val;
+       MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
+
+       /* delete the entire attribute */
+       if ( mod->sm_bvalues == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify_delete: removing entire attribute %s\n",
+                       desc, 0, 0 );
+               return attr_delete( &e->e_attrs, mod->sm_desc )
+                       ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS;
+       }
+
+       if( mr == NULL || !mr->smr_match ) {
+               /* disallow specific attributes from being deleted if
+                       no equality rule */
+               return LDAP_INAPPROPRIATE_MATCHING;
+       }
+
+       /* delete specific values - find the attribute first */
+       if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify_delete: could not find attribute %s\n",
+                       desc, 0, 0 );
+               return LDAP_NO_SUCH_ATTRIBUTE;
+       }
+
+       /* find each value to delete */
+       for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+               int rc;
+               const char *text = NULL;
+
+               struct berval *asserted;
+
+               rc = value_normalize( mod->sm_desc,
+                       SLAP_MR_EQUALITY,
+                       mod->sm_bvalues[i],
+                       &asserted,
+                       &text );
+
+               if( rc != LDAP_SUCCESS ) return rc;
+
+               found = 0;
+               for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+                       int match;
+                       int rc = value_match( &match, mod->sm_desc, mr,
+                               SLAP_MR_MODIFY_MATCHING,
+                               a->a_vals[j], asserted, &text );
+
+                       if( rc == LDAP_SUCCESS && match != 0 ) {
+                               continue;
+                       }
+
+                       /* found a matching value */
+                       found = 1;
+
+                       /* delete it */
+                       ber_bvfree( a->a_vals[j] );
+                       for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
+                               a->a_vals[k - 1] = a->a_vals[k];
+                       }
+                       a->a_vals[k - 1] = NULL;
+
+                       break;
+               }
+
+               ber_bvfree( asserted );
+
+               /* looked through them all w/o finding it */
+               if ( ! found ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modify_delete: could not find value for attr %s\n",
+                               desc, 0, 0 );
+                       return LDAP_NO_SUCH_ATTRIBUTE;
+               }
+       }
+
+       /* if no values remain, delete the entire attribute */
+       if ( a->a_vals[0] == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modify_delete: removing entire attribute %s\n",
+                       desc, 0, 0 );
+               if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
+                       return LDAP_NO_SUCH_ATTRIBUTE;
+               }
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int
+replace_values(
+       Entry   *e,
+       Modification    *mod,
+       char    *dn
+)
+{
+       int rc = attr_delete( &e->e_attrs, mod->sm_desc );
+
+       if( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+               return rc;
+       }
+
+       if ( mod->sm_bvalues != NULL &&
+               attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 )
+       {
+               return LDAP_OTHER;
+       }
+
+       return LDAP_SUCCESS;
+}
diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c
new file mode 100644 (file)
index 0000000..456f1b4
--- /dev/null
@@ -0,0 +1,534 @@
+/* modrdn.c - bdb backend modrdn routine */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+int
+bdb_modrdn(
+       Backend *be,
+       Connection      *conn,
+       Operation       *op,
+       const char      *dn,
+       const char      *ndn,
+       const char      *newrdn,
+       int             deleteoldrdn,
+       const char      *newSuperior
+)
+{
+       struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+       AttributeDescription *children = slap_schema.si_ad_children;
+       char            *p_dn = NULL, *p_ndn = NULL;
+       char            *new_dn = NULL, *new_ndn = NULL;
+       Entry           *e, *p = NULL;
+       Entry           *matched;
+       int                     rc;
+       const char *text = NULL;
+       DB_TXN *        ltid;
+       struct bdb_op_info opinfo;
+
+       ID                      id;
+       char            *new_rdn_val = NULL;    /* Val of new rdn */
+       char            *new_rdn_type = NULL;   /* Type of new rdn */
+       char            *old_rdn = NULL;                /* Old rdn's attr type & val */
+       char            *old_rdn_type = NULL;   /* Type of old rdn attr. */
+       char            *old_rdn_val = NULL;    /* Old rdn attribute value */
+
+       Entry           *np = NULL;                             /* newSuperior Entry */
+       char            *np_dn = NULL;                  /* newSuperior dn */
+       char            *np_ndn = NULL;                 /* newSuperior ndn */
+       char            *new_parent_dn = NULL;  /* np_dn, p_dn, or NULL */
+
+       /* Used to interface with bdb_modify_internal() */
+       struct berval   add_bv;                         /* Stores new rdn att */
+       struct berval   *add_bvals[2];          /* Stores new rdn att */
+       struct berval   del_bv;                         /* Stores old rdn att */
+       struct berval   *del_bvals[2];          /* Stores old rdn att */
+       Modifications   mod[2];                         /* Used to delete old rdn */
+
+       int             manageDSAit = get_manageDSAit( op );
+
+       Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n",
+               dn, newrdn, (newSuperior ? newSuperior : "NULL") );
+
+       if (0) {
+               /* transaction retry */
+retry: rc = txn_abort( ltid );
+               ltid = NULL;
+               op->o_private = NULL;
+               if( rc != 0 ) {
+                       rc = LDAP_OTHER;
+                       text = "internal error";
+                       goto return_results;
+               }
+       }
+
+       /* begin transaction */
+       rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_delete: txn_begin failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               text = "internal error";
+               goto return_results;
+       }
+
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
+
+       /* get entry */
+       rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
+
+       switch( rc ) {
+       case 0:
+       case DB_NOTFOUND:
+               break;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto retry;
+       default:
+               rc = LDAP_OTHER;
+               text = "internal error";
+               goto return_results;
+       }
+
+       if ( e == NULL ) {
+               char* matched_dn = NULL;
+               struct berval** refs = NULL;
+
+               if( matched != NULL ) {
+                       matched_dn = strdup( matched->e_dn );
+                       refs = is_entry_referral( matched )
+                               ? get_entry_referrals( be, conn, op, matched )
+                               : NULL;
+                       bdb_entry_return( be, matched );
+               } else {
+                       refs = default_referral;
+               }
+
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       matched_dn, NULL, refs, NULL );
+
+               if ( matched != NULL ) {
+                       ber_bvecfree( refs );
+                       free( matched_dn );
+               }
+
+               goto done;
+       }
+
+       if (!manageDSAit && is_entry_referral( e ) ) {
+               /* parent is a referral, don't allow add */
+               /* parent is an alias, don't allow add */
+               struct berval **refs = get_entry_referrals( be,
+                       conn, op, e );
+
+               Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
+                       0, 0, 0 );
+
+               send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+                       e->e_dn, NULL, refs, NULL );
+
+               ber_bvecfree( refs );
+               goto done;
+       }
+
+       p_ndn = dn_parent( be, e->e_ndn );
+       if ( p_ndn != NULL ) {
+               /* Make sure parent entry exist and we can write its 
+                * children.
+                */
+
+               rc = bdb_dn2entry( be, ltid, p_ndn, &p, NULL, 0 );
+
+               switch( rc ) {
+               case 0:
+               case DB_NOTFOUND:
+                       break;
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               default:
+                       rc = LDAP_OTHER;
+                       text = "internal error";
+                       goto return_results;
+               }
+
+               if( p == NULL) {
+                       Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n",
+                               0, 0, 0);
+                       rc = LDAP_OTHER;
+                       goto return_results;
+               }
+
+               /* check parent for "children" acl */
+               if ( ! access_allowed( be, conn, op, p,
+                       children, NULL, ACL_WRITE ) )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+                               0, 0 );
+                       send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+                               NULL, NULL, NULL, NULL );
+                       goto return_results;
+               }
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: wr to children of entry %s OK\n",
+                       p_ndn, 0, 0 );
+               
+               p_dn = dn_parent( be, e->e_dn );
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: parent dn=%s\n",
+                       p_dn, 0, 0 );
+
+       } else {
+               /* no parent, modrdn entry directly under root */
+               if( ! be_isroot( be, op->o_ndn ) ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modrdn: no parent & not root\n",
+                               0, 0, 0);
+                       rc = LDAP_INSUFFICIENT_ACCESS;
+                       goto return_results;
+               }
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: no parent, locked root\n",
+                       0, 0, 0 );
+       }
+
+       new_parent_dn = p_dn;   /* New Parent unless newSuperior given */
+
+       if ( newSuperior != NULL ) {
+               Debug( LDAP_DEBUG_TRACE, 
+                       "bdb_modrdn: new parent \"%s\" requested...\n",
+                       newSuperior, 0, 0 );
+
+               np_dn = ch_strdup( newSuperior );
+               np_ndn = ch_strdup( np_dn );
+               (void) dn_normalize( np_ndn );
+
+               /* newSuperior == oldParent?, if so ==> ERROR */
+               /* newSuperior == entry being moved?, if so ==> ERROR */
+               /* Get Entry with dn=newSuperior. Does newSuperior exist? */
+
+               rc = bdb_dn2entry( be, ltid, np_ndn, &np, NULL, 0 );
+
+               switch( rc ) {
+               case 0:
+               case DB_NOTFOUND:
+                       break;
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               default:
+                       rc = LDAP_OTHER;
+                       text = "internal error";
+                       goto return_results;
+               }
+
+               if( np == NULL) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modrdn: newSup(ndn=%s) not here!\n",
+                               np_ndn, 0, 0);
+                       rc = LDAP_OTHER;
+                       goto return_results;
+               }
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
+                       np, np->e_id, 0 );
+
+               /* check newSuperior for "children" acl */
+               if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modrdn: no wr to newSup children\n",
+                               0, 0, 0 );
+                       rc = LDAP_INSUFFICIENT_ACCESS;
+                       goto return_results;
+               }
+
+               if ( is_entry_alias( np ) ) {
+                       /* entry is an alias, don't allow bind */
+                       Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n",
+                               0, 0, 0 );
+
+                       rc = LDAP_ALIAS_PROBLEM;
+                       goto return_results;
+               }
+
+               if ( is_entry_referral( np ) ) {
+                       /* parent is a referral, don't allow add */
+                       /* parent is an alias, don't allow add */
+                       Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
+                               0, 0, 0 );
+
+                       rc = LDAP_OPERATIONS_ERROR;
+                       goto return_results;
+               }
+
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: wr to new parent's children OK\n",
+                       0, 0, 0 );
+
+               new_parent_dn = np_dn;
+       }
+       
+       /* Build target dn and make sure target entry doesn't exist already. */
+       build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn ); 
+
+       new_ndn = ch_strdup(new_dn);
+       (void) dn_normalize( new_ndn );
+
+       Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n",
+               new_ndn, 0, 0 );
+
+       rc = bdb_dn2id ( be, ltid, new_ndn, &id );
+       if( rc != 0 ) {
+               switch( rc ) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto retry;
+               default:
+                       rc = LDAP_OTHER;
+                       text = "internal error";
+               }
+
+               goto return_results;
+       }
+
+       Debug( LDAP_DEBUG_TRACE,
+               "bdb_modrdn: new ndn=%s does not exist\n",
+               new_ndn, 0, 0 );
+
+       /* Get attribute type and attribute value of our new rdn, we will
+        * need to add that to our new entry
+        */
+
+       new_rdn_type = rdn_attr_type( newrdn );
+       if ( new_rdn_type == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: can't figure out type of newrdn\n",
+                       0, 0, 0 );
+               rc = LDAP_OPERATIONS_ERROR;
+               text = "unknown type used in RDN";
+               goto return_results;            
+       }
+
+       new_rdn_val = rdn_attr_value( newrdn );
+       if ( new_rdn_val == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: could not figure out val of newrdn\n",
+                       0, 0, 0 );
+               rc = LDAP_OPERATIONS_ERROR;
+               text = "could not parse RDN value";
+               goto return_results;            
+       }
+
+       Debug( LDAP_DEBUG_TRACE,
+               "bdb_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
+               new_rdn_val, new_rdn_type, 0 );
+
+       /* Retrieve the old rdn from the entry's dn */
+
+       if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: can't figure out old_rdn from dn\n",
+                       0, 0, 0 );
+               rc = LDAP_OTHER;
+               text = "could not parse old DN";
+               goto return_results;            
+       }
+
+       if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_back_modrdn: can't figure out the old_rdn type\n",
+                       0, 0, 0 );
+               rc = LDAP_OTHER;
+               text = "cannot parse RDN from old DN";
+               goto return_results;            
+       }
+       
+       if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+               /* Not a big deal but we may say something */
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+                       old_rdn_type, new_rdn_type, 0 );
+       }               
+
+       /* Add new attribute value to the entry */
+       add_bvals[0] = &add_bv;         /* Array of bervals */
+       add_bvals[1] = NULL;
+
+       add_bv.bv_val = new_rdn_val;
+       add_bv.bv_len = strlen(new_rdn_val);
+               
+       mod[0].sml_desc = NULL;
+       rc = slap_str2ad( new_rdn_type, &mod[0].sml_desc, &text );
+
+       if( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: %s: %s (new)\n",
+                       text, new_rdn_type, 0 );
+               goto return_results;            
+       }
+       mod[0].sml_bvalues = add_bvals;
+       mod[0].sml_op = SLAP_MOD_SOFTADD;
+       mod[0].sml_next = NULL;
+
+       /* Remove old rdn value if required */
+
+       if (deleteoldrdn) {
+               /* Get value of old rdn */
+               old_rdn_val = rdn_attr_value( old_rdn );
+               if ( old_rdn_val == NULL) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modrdn: can't figure out old_rdn_val from old_rdn\n",
+                               0, 0, 0 );
+                       rc = LDAP_OTHER;
+                       text = "could not parse value from old RDN";
+                       goto return_results;            
+               }
+
+               del_bvals[0] = &del_bv;         /* Array of bervals */
+               del_bvals[1] = NULL;
+
+               /* Remove old value of rdn as an attribute. */
+               del_bv.bv_val = old_rdn_val;
+               del_bv.bv_len = strlen(old_rdn_val);
+
+               mod[1].sml_desc = NULL;
+               rc = slap_str2ad( old_rdn_type, &mod[1].sml_desc, &text );
+
+               if( rc != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "bdb_modrdn: %s: %s (old)\n",
+                               text, old_rdn_type, 0 );
+                       goto return_results;            
+               }
+
+               mod[0].sml_next = &mod[1];
+               mod[1].sml_bvalues = del_bvals;
+               mod[1].sml_op = LDAP_MOD_DELETE;
+               mod[1].sml_next = NULL;
+       }
+       
+       /* delete old one */
+       rc = bdb_dn2id_delete( be, ltid, e->e_ndn, e->e_id );
+       if ( rc != 0 ) {
+               rc = LDAP_OTHER;
+               text = "DN index delete fail";
+               goto return_results;
+       }
+
+       free( e->e_dn );
+       free( e->e_ndn );
+       e->e_dn = new_dn;
+       e->e_ndn = new_ndn;
+       new_dn = NULL;
+       new_ndn = NULL;
+
+       /* add new one */
+       rc = bdb_dn2id_add( be, ltid, e->e_ndn, e->e_id );
+       if ( rc != 0 ) {
+               rc = LDAP_OTHER;
+               text = "DN index add failed";
+               goto return_results;
+       }
+
+       /* modify entry */
+       rc = bdb_modify_internal( be, conn, op, ltid, dn, &mod[0], e, &text );
+
+       if( rc != LDAP_SUCCESS ) {
+               goto return_results;
+       }
+       
+       /* NOTE: after this you must not free new_dn or new_ndn!
+        * They are used by cache.
+        */
+
+       /* id2entry index */
+       rc = bdb_id2entry_add( be, ltid, e );
+       if ( rc != 0 ) {
+               rc = LDAP_OTHER;
+               text = "entry update failed";
+               goto return_results;
+       }
+
+       rc = LDAP_SUCCESS;
+
+       rc = txn_commit( ltid, 0 );
+       ltid = NULL;
+       op->o_private = NULL;
+
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: txn_commit failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               text = "commit failed";
+       } else {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_modrdn: added id=%08x dn=\"%s\"\n",
+                       e->e_id, e->e_dn, 0 );
+               rc = LDAP_SUCCESS;
+               text = NULL;
+       }
+
+return_results:
+       send_ldap_result( conn, op, rc,
+               NULL, text, NULL, NULL );
+
+done:
+       if( new_dn != NULL ) free( new_dn );
+       if( new_ndn != NULL ) free( new_ndn );
+
+       if( p_dn != NULL ) free( p_dn );
+       if( p_ndn != NULL ) free( p_ndn );
+
+       /* LDAP v2 supporting correct attribute handling. */
+       if( new_rdn_type != NULL ) free(new_rdn_type);
+       if( new_rdn_val != NULL ) free(new_rdn_val);
+       if( old_rdn != NULL ) free(old_rdn);
+       if( old_rdn_type != NULL ) free(old_rdn_type);
+       if( old_rdn_val != NULL ) free(old_rdn_val);
+
+
+       /* LDAP v3 Support */
+       if ( np_dn != NULL ) free( np_dn );
+       if ( np_ndn != NULL ) free( np_ndn );
+
+       if( np != NULL ) {
+               /* free new parent and writer lock */
+               bdb_entry_return( be, np );
+       }
+
+       if( p != NULL ) {
+               /* free parent and writer lock */
+               bdb_entry_return( be, p );
+       }
+
+       /* free entry */
+       if( e != NULL ) {
+               bdb_entry_return( be, e );
+       }
+
+       if( ltid != NULL ) {
+               txn_abort( ltid );
+               op->o_private = NULL;
+       }
+
+       return rc;
+}
index 1639a62979978f6ae3f5916d2bc90e453ab8f8d8..2731bd5a73fbf83be1ffc2b23b7dc0e957ccb649 100644 (file)
 
 int
 bdb_exop_passwd(
-    Backend            *be,
-    Connection         *conn,
-    Operation          *op,
+       Backend         *be,
+       Connection              *conn,
+       Operation               *op,
        const char              *reqoid,
-    struct berval      *reqdata,
+       struct berval   *reqdata,
        char                    **rspoid,
-    struct berval      **rspdata,
+       struct berval   **rspdata,
        LDAPControl             *** rspctrls,
        const char              **text,
-    struct berval      *** refs
-)
+       struct berval   *** refs )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        int rc;
        Entry *e = NULL;
        struct berval *hash = NULL;
-       DB_TXN *ltid;
+       DB_TXN *ltid = NULL;
+       struct bdb_op_info opinfo;
 
        struct berval *id = NULL;
        struct berval *new = NULL;
@@ -82,17 +82,48 @@ bdb_exop_passwd(
                goto done;
        }
 
-       /* fetch entry */
-       rc = dn2entry_w( be, NULL, dn, &e, NULL );
+       if (0) {
+               /* transaction retry */
+retry: rc = txn_abort( ltid );
+               ltid = NULL;
+               op->o_private = NULL;
+               if( rc != 0 ) {
+                       rc = LDAP_OTHER;
+                       *text = "internal error";
+                       goto done;
+               }
+       }
+
+       /* begin transaction */
+       rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_exop_passwd: txn_begin failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               *text = "internal error";
+               goto done;
+       }
+
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
+
+       /* get entry */
+       rc = bdb_dn2entry( be, ltid, dn, &e, NULL, 0 );
 
        switch(rc) {
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto retry;
        case DB_NOTFOUND:
        case 0:
                break;
        default:
-               send_ldap_result( conn, op, rc=LDAP_OTHER,
-                   NULL, "internal error", NULL, NULL );
-               return rc;
+               rc = LDAP_OTHER;
+               *text = "internal error";
+               goto done;
        }
 
        if( e == NULL ) {
@@ -108,11 +139,11 @@ bdb_exop_passwd(
                goto done;
        }
 
-       rc = LDAP_OPERATIONS_ERROR;
 
        if( is_entry_referral( e ) ) {
                /* entry is an referral, don't allow operation */
                *text = "authorization entry is referral";
+               rc = LDAP_OPERATIONS_ERROR;
                goto done;
        }
 
@@ -128,19 +159,39 @@ bdb_exop_passwd(
                ml.sml_op = LDAP_MOD_REPLACE;
                ml.sml_next = NULL;
 
-               rc = bdb_modify_internal( be,
-                       conn, op, op->o_ndn, &ml, e, text );
+               rc = bdb_modify_internal( be, conn, op, ltid,
+                       op->o_ndn, &ml, e, text );
+
+               switch(rc) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       bdb_entry_return( be, e );
+                       e = NULL;
+                       goto retry;
+               case 0:
+                       break;
+               default:
+                       rc = LDAP_OTHER;
+                       *text = "entry modify failed";
+                       goto done;
+               }
 
        }
 
-       if( rc == LDAP_SUCCESS ) {
-               /* change the entry itself */
-               if( bdb_id2entry_add( be, ltid, e ) != 0 ) {
-                       *text = "entry update failed";
-                       rc = LDAP_OTHER;
+       /* change the entry itself */
+       rc = bdb_id2entry_update( be, ltid, e );
+       if( rc != 0 ) {
+               switch(rc) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       bdb_entry_return( be, e );
+                       goto retry;
                }
+               *text = "entry update failed";
+               rc = LDAP_OTHER;
+               goto done;
        }
-       
+
 done:
        if( e != NULL ) {
                bdb_entry_return( be, e );
@@ -158,5 +209,10 @@ done:
                ber_bvfree( hash );
        }
 
+       if( ltid != NULL ) {
+               txn_abort( ltid );
+               op->o_private = NULL;
+       }
+
        return rc;
 }
index 111b51685d1783f865f692d0c460abfcd3651c36..e4cc6e11fd14e0b990fdb1dad00378d42522d8af 100644 (file)
@@ -31,12 +31,6 @@ Entry *bdb_deref_internal_r LDAP_P((
 int bdb_dn2entry LDAP_P(( BackendDB *be, DB_TXN *tid,
        const char *dn, Entry **e, Entry **matched, int flags ));
 
-#define dn2entry_r(be, tid, dn, p, m) \
-       bdb_dn2entry((be), (tid), (dn), (p), (m), 0 )
-
-#define dn2entry_w(be, tid, dn, p, m) \
-       bdb_dn2entry((be), (tid), (dn), (p), (m), DB_RMW )
-
 /*
  * dn2id.c
  */
@@ -88,6 +82,11 @@ int bdb_id2entry_add(
        DB_TXN *tid,
        Entry *e );
 
+int bdb_id2entry_update(
+       BackendDB *be,
+       DB_TXN *tid,
+       Entry *e );
+
 int bdb_id2entry_delete(
        BackendDB *be,
        DB_TXN *tid,
@@ -123,6 +122,35 @@ int bdb_idl_delete_key(
  */
 int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *id );
 
+/*
+ * modify.c
+ */
+int bdb_modify_internal(
+       BackendDB *be,
+       Connection *conn,
+       Operation *op,
+       DB_TXN *tid,
+       const char *dn,
+       Modifications *modlist,
+       Entry *e,
+       const char **text );
+
+/*
+ * passwd.c
+ */
+int
+bdb_exop_passwd(
+       Backend         *be,
+       Connection              *conn,
+       Operation               *op,
+       const char              *reqoid,
+       struct berval   *reqdata,
+       char                    **rspoid,
+       struct berval   **rspdata,
+       LDAPControl             *** rspctrls,
+       const char              **text,
+       struct berval   *** refs );
+
 /*
  * tools.c
  */
index ef8e5d7ca1e66faa5b3aadf84b149d191642a75c..f4e2a08c70266c2f45e995fd6ff684cab109ca7e 100644 (file)
 
 int
 bdb_referrals(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    const char *dn,
-    const char *ndn,
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char *dn,
+       const char *ndn,
        const char **text )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
@@ -35,8 +35,8 @@ bdb_referrals(
                return rc;
        } 
 
-       /* fetch entry */
-       rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+       /* get entry */
+       rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -44,7 +44,7 @@ bdb_referrals(
                break;
        default:
                send_ldap_result( conn, op, rc=LDAP_OTHER,
-                   NULL, "internal error", NULL, NULL );
+                       NULL, "internal error", NULL, NULL );
                return rc;
        }
 
@@ -91,7 +91,7 @@ bdb_referrals(
 
                if( refs != NULL ) {
                        send_ldap_result( conn, op, rc = LDAP_REFERRAL,
-                       e->e_dn, NULL, refs, NULL );
+                               e->e_dn, NULL, refs, NULL );
                }
 
                ber_bvecfree( refs );
index 78a16e48a806fd728c62e02324d87cb6ad77aef2..9ae8746ec996a3169cecbe5f98a3e53ee697b7d8 100644 (file)
 #include "external.h"
 
 static int base_candidate(
-    BackendDB  *be,
+       BackendDB       *be,
        Entry   *e,
        ID              *ids );
 static int search_candidates(
        BackendDB *be,
        Entry *e,
        Filter *filter,
-    int scope,
+       int scope,
        int deref,
        int manageDSAit,
        ID      *ids );
@@ -31,19 +31,19 @@ static ID idl_next( ID *ids, ID *cursor );
 
 int
 bdb_search(
-    BackendDB  *be,
-    Connection *conn,
-    Operation  *op,
-    const char *base,
-    const char *nbase,
-    int                scope,
-    int                deref,
-    int                slimit,
-    int                tlimit,
-    Filter     *filter,
-    const char *filterstr,
-    char       **attrs,
-    int                attrsonly )
+       BackendDB       *be,
+       Connection      *conn,
+       Operation       *op,
+       const char      *base,
+       const char      *nbase,
+       int             scope,
+       int             deref,
+       int             slimit,
+       int             tlimit,
+       Filter  *filter,
+       const char      *filterstr,
+       char    **attrs,
+       int             attrsonly )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        int              abandon;
@@ -72,8 +72,7 @@ bdb_search(
        } else
 #endif
        {
-               /* obtain entry */
-               rc = dn2entry_r( be, NULL, nbase, &e, &matched );
+               rc = bdb_dn2entry( be, NULL, nbase, &e, &matched, 0 );
        }
 
        switch(rc) {
@@ -82,7 +81,7 @@ bdb_search(
                break;
        default:
                send_ldap_result( conn, op, rc=LDAP_OTHER,
-                   NULL, "internal error", NULL, NULL );
+                       NULL, "internal error", NULL, NULL );
                return rc;
        }
 
@@ -125,7 +124,7 @@ bdb_search(
                        0, 0, 0 );
 
                send_ldap_result( conn, op, LDAP_REFERRAL,
-                   matched_dn, NULL, refs, NULL );
+                       matched_dn, NULL, refs, NULL );
 
                ber_bvecfree( refs );
                free( matched_dn );
@@ -137,7 +136,7 @@ bdb_search(
                tlimit = -1;    /* allow root to set no limit */
        } else {
                tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
-                   be->be_timelimit : tlimit;
+                       be->be_timelimit : tlimit;
                stoptime = op->o_time + tlimit;
        }
 
@@ -145,7 +144,7 @@ bdb_search(
                slimit = -1;    /* allow root to set no limit */
        } else {
                slimit = (slimit > be->be_sizelimit || slimit < 1) ?
-                   be->be_sizelimit : slimit;
+                       be->be_sizelimit : slimit;
        }
 
        if ( scope == LDAP_SCOPE_BASE ) {
@@ -153,7 +152,7 @@ bdb_search(
 
        } else {
                rc = search_candidates( be, e, filter,
-                   scope, deref, manageDSAit, candidates );
+                       scope, deref, manageDSAit, candidates );
        }
 
        /* need normalized dn below */
@@ -178,7 +177,7 @@ bdb_search(
 
        for ( id = idl_first( candidates, &cursor );
                id != NOID;
-           id = idl_next( candidates, &cursor ) )
+               id = idl_next( candidates, &cursor ) )
        {
                int             scopeok = 0;
 
@@ -357,7 +356,7 @@ done:
 
 
 static int base_candidate(
-    BackendDB  *be,
+       BackendDB       *be,
        Entry   *e,
        ID              *ids )
 {
@@ -373,20 +372,72 @@ static int search_candidates(
        BackendDB *be,
        Entry *e,
        Filter *filter,
-    int scope,
+       int scope,
        int deref,
        int manageDSAit,
        ID      *ids )
 {
-       Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" (0x%08lx)\n",
-               e->e_dn, (long) e->e_id, 0);
+       int rc;
+       Filter          f, fand, rf, af, xf;
+       AttributeAssertion aa_ref, aa_alias;
+
+       Debug(LDAP_DEBUG_TRACE,
+               "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
+               e->e_dn, (long) e->e_id, scope );
+
+       xf.f_or = filter;
+       xf.f_choice = LDAP_FILTER_OR;
+       xf.f_next = NULL;
+
+       if( !manageDSAit ) {
+               /* match referrals */
+               static struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
+               rf.f_choice = LDAP_FILTER_EQUALITY;
+               rf.f_ava = &aa_ref;
+               rf.f_av_desc = slap_schema.si_ad_objectClass;
+               rf.f_av_value = &bv_ref;
+               rf.f_next = xf.f_or;
+               xf.f_or = &rf;
+       }
+
+#ifdef BDB_ALIASES
+       if( deref & LDAP_DEREF_SEARCHING ) {
+               /* match aliases */
+               static struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
+               af.f_choice = LDAP_FILTER_EQUALITY;
+               af.f_ava = &aa_alias;
+               af.f_av_desc = slap_schema.si_ad_objectClass;
+               af.f_av_value = &bv_alias;
+               af.f_next = xf.f_or;
+               xf.f_or = &af;
+       }
+#endif
 
-       /* return a RANGE IDL for now */
+       f.f_next = NULL;
+       f.f_choice = LDAP_FILTER_AND;
+       f.f_and = &fand;
+       fand.f_choice = scope == LDAP_SCOPE_SUBTREE
+               ? SLAPD_FILTER_DN_SUBTREE
+               : SLAPD_FILTER_DN_ONE;
+       fand.f_dn = e->e_ndn;
+       fand.f_next = xf.f_or == filter ? filter : &xf ;
+
+#if 0
+       rc = bdb_filter_candidates( be, &f, ids );
+#else
+       /* a quick hack */
        ids[0] = NOID;
        ids[1] = e->e_id;
        ids[2] = e->e_id+128;
+       rc = 0;
+#endif
 
-       return 0;
+       Debug(LDAP_DEBUG_TRACE,
+               "search_candidates: id=%ld first=%ld last=%ld\n",
+               ids[0], ids[1],
+               BDB_IDL_IS_RANGE( ids ) ? ids[2] : ids[ids[0]] );
+
+       return rc;
 }
 
 static ID idl_first( ID *ids, ID *cursor )