]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/chain.c
Merge remote-tracking branch 'origin/mdb.RE/0.9' into OPENLDAP_REL_ENG_2_4
[openldap] / servers / slapd / back-ldap / chain.c
index f9e3ac157c8c8a003f82e08e068a522e7e7f5b3b..1b9bd8654d7841b4a71a4bc2a7708c66d35d667f 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2011 The OpenLDAP Foundation.
+ * Copyright 2003-2015 The OpenLDAP Foundation.
  * Portions Copyright 2003 Howard Chu.
  * All rights reserved.
  *
@@ -196,12 +196,13 @@ chaining_control_remove(
         * added by the chain overlay, so it's the only one we explicitly 
         * free */
        if ( op->o_ctrls != oldctrls ) {
-               assert( op->o_ctrls != NULL );
-               assert( op->o_ctrls[ 0 ] != NULL );
+               if ( op->o_ctrls != NULL ) {
+                       assert( op->o_ctrls[ 0 ] != NULL );
 
-               free( op->o_ctrls );
+                       free( op->o_ctrls );
 
-               op->o_chaining = 0;
+                       op->o_chaining = 0;
+               }
                op->o_ctrls = oldctrls;
        } 
 
@@ -225,7 +226,6 @@ ldap_chain_uri_cmp( const void *c1, const void *c2 )
        assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
        assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
 
-       /* If local DNs don't match, it is definitely not a match */
        return ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] );
 }
 
@@ -243,11 +243,10 @@ ldap_chain_uri_dup( void *c1, void *c2 )
        assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
        assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
 
-       /* Cannot have more than one shared session with same DN */
        if ( ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ) == 0 ) {
                return -1;
        }
-               
+
        return 0;
 }
 
@@ -322,6 +321,10 @@ ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
 
                /* back-ldap tried to send result */
                lb->lb_status = LDAP_CH_RES;
+               /* don't let other callbacks run, this isn't
+                * the real result for this op.
+                */
+               op->o_callback->sc_next = NULL;
        }
 
        return 0;
@@ -625,6 +628,11 @@ cleanup:;
                }
 
 further_cleanup:;
+               if ( op->o_req_dn.bv_val == pdn.bv_val ) {
+                       op->o_req_dn = odn;
+                       op->o_req_ndn = ondn;
+               }
+
                if ( free_dn ) {
                        op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );
                        op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
@@ -650,9 +658,6 @@ further_cleanup:;
                rc = rs2.sr_err;
        }
 
-       op->o_req_dn = odn;
-       op->o_req_ndn = ondn;
-
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
        (void)chaining_control_remove( op, &ctrls );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
@@ -896,14 +901,16 @@ cleanup:;
                }
                
 further_cleanup:;
+               if ( op->o_req_dn.bv_val == pdn.bv_val ) {
+                       op->o_req_dn = odn;
+                       op->o_req_ndn = ondn;
+               }
+
                if ( free_dn ) {
                        op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );
                        op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
                }
 
-               op->o_req_dn = odn;
-               op->o_req_ndn = ondn;
-
                if ( tmp_oq_search.rs_filter != NULL ) {
                        filter_free_x( op, tmp_oq_search.rs_filter, 1 );
                }
@@ -926,8 +933,6 @@ further_cleanup:;
        (void)chaining_control_remove( op, &ctrls );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
-       op->o_req_dn = odn;
-       op->o_req_ndn = ondn;
        rs->sr_type = REP_SEARCHREF;
        rs->sr_entry = save_entry;
        rs->sr_flags = save_flags;
@@ -1223,6 +1228,9 @@ enum {
 static ConfigDriver chain_cf_gen;
 static ConfigCfAdd chain_cfadd;
 static ConfigLDAPadd chain_ldadd;
+#ifdef SLAP_CONFIG_DELETE
+static ConfigLDAPdel chain_lddel;
+#endif
 
 static ConfigTable chaincfg[] = {
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
@@ -1269,8 +1277,12 @@ static ConfigOCs chainocs[] = {
        { "( OLcfgOvOc:3.2 "
                "NAME 'olcChainDatabase' "
                "DESC 'Chain remote server configuration' "
-               "SUP olcLDAPConfig )",
-               Cft_Misc, olcDatabaseDummy, chain_ldadd },
+               "AUXILIARY )",
+               Cft_Misc, olcDatabaseDummy, chain_ldadd
+#ifdef SLAP_CONFIG_DELETE
+               , NULL, chain_lddel
+#endif
+       },
        { NULL, 0, NULL }
 };
 
@@ -1333,12 +1345,16 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 
        if ( lc->lc_common_li == NULL ) {
                rc = ldap_chain_db_init_common( ca->be );
+               if ( rc != 0 )
+                       goto fail;
+               li = ca->be->be_private;
+               lc->lc_common_li = lc->lc_cfg_li = li;
 
-       } else {
-               rc = ldap_chain_db_init_one( ca->be );
        }
+       rc = ldap_chain_db_init_one( ca->be );
 
        if ( rc != 0 ) {
+fail:
                Debug( LDAP_DEBUG_ANY, "slapd-chain: "
                        "unable to init %sunderlying database \"%s\".\n",
                        lc->lc_common_li == NULL ? "common " : "", e->e_name.bv_val, 0 );
@@ -1347,10 +1363,7 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 
        li = ca->be->be_private;
 
-       if ( lc->lc_common_li == NULL ) {
-               lc->lc_common_li = li;
-
-       } else {
+       if ( at ) {
                li->li_uri = ch_strdup( at->a_vals[ 0 ].bv_val );
                value_add_one( &li->li_bvuri, &at->a_vals[ 0 ] );
                if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li,
@@ -1434,6 +1447,45 @@ chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )
        return 0;
 }
 
+#ifdef SLAP_CONFIG_DELETE
+static int
+chain_lddel( CfEntryInfo *ce, Operation *op )
+{
+       CfEntryInfo     *pe = ce->ce_parent;
+       slap_overinst   *on = (slap_overinst *)pe->ce_bi;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       ldapinfo_t      *li = (ldapinfo_t *) ce->ce_be->be_private;
+
+       if ( li != lc->lc_common_li ) {
+               if (! avl_delete( &lc->lc_lai.lai_tree, li, ldap_chain_uri_cmp ) ) {
+                       Debug( LDAP_DEBUG_ANY, "slapd-chain: avl_delete failed. "
+                               "\"%s\" not found.\n", li->li_uri, 0, 0 );
+                       return -1;
+               }
+       } else if ( lc->lc_lai.lai_tree ) {
+               Debug( LDAP_DEBUG_ANY, "slapd-chain: cannot delete first underlying "
+                       "LDAP database when other databases are still present.\n", 0, 0, 0 );
+               return -1;
+       } else {
+               lc->lc_common_li = NULL;
+       }
+
+       ce->ce_be->bd_info = lback;
+
+       if ( ce->ce_be->bd_info->bi_db_close ) {
+               ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
+       }
+       if ( ce->ce_be->bd_info->bi_db_destroy ) {
+               ce->ce_be->bd_info->bi_db_destroy( ce->ce_be, NULL );
+       }
+
+       ch_free(ce->ce_be);
+       ce->ce_be = NULL;
+
+       return LDAP_SUCCESS;
+}
+#endif /* SLAP_CONFIG_DELETE */
+
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 static slap_verbmasks chaining_mode[] = {
        { BER_BVC("referralsRequired"),         LDAP_REFERRALS_REQUIRED },
@@ -1721,20 +1773,17 @@ ldap_chain_db_config(
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
 
        int             rc = SLAP_CONF_UNKNOWN;
-               
+
        if ( lc->lc_common_li == NULL ) {
-               void    *be_private = be->be_private;
-               ldap_chain_db_init_common( be );
-               lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)be->be_private;
-               be->be_private = be_private;
+               BackendDB db = *be;
+               ldap_chain_db_init_common( &db );
+               lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)db.be_private;
        }
 
        /* Something for the chain database? */
        if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {
                char            *save_argv0 = argv[ 0 ];
-               BackendInfo     *bd_info = be->bd_info;
-               void            *be_private = be->be_private;
-               ConfigOCs       *be_cf_ocs = be->be_cf_ocs;
+               BackendDB       db = *be;
                static char     *allowed_argv[] = {
                        /* special: put URI here, so in the meanwhile
                         * it detects whether a new URI is being provided */
@@ -1773,14 +1822,14 @@ ldap_chain_db_config(
                }
 
                if ( which_argv == 0 ) {
-                       rc = ldap_chain_db_init_one( be );
+                       rc = ldap_chain_db_init_one( &db );
                        if ( rc != 0 ) {
                                Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                        "underlying slapd-ldap initialization failed.\n.",
                                        fname, lineno, 0 );
                                return 1;
                        }
-                       lc->lc_cfg_li = be->be_private;
+                       lc->lc_cfg_li = db.be_private;
                }
 
                /* TODO: add checks on what other slapd-ldap(5) args
@@ -1790,27 +1839,21 @@ ldap_chain_db_config(
                 * be warned.
                 */
 
-               be->bd_info = lback;
-               be->be_private = (void *)lc->lc_cfg_li;
-               be->be_cf_ocs = lback->bi_cf_ocs;
+               db.bd_info = lback;
+               db.be_private = (void *)lc->lc_cfg_li;
+               db.be_cf_ocs = lback->bi_cf_ocs;
 
-               rc = config_generic_wrapper( be, fname, lineno, argc, argv );
+               rc = config_generic_wrapper( &db, fname, lineno, argc, argv );
 
                argv[ 0 ] = save_argv0;
-               be->be_cf_ocs = be_cf_ocs;
-               be->be_private = be_private;
-               be->bd_info = bd_info;
 
                if ( which_argv == 0 ) {
 private_destroy:;
                        if ( rc != 0 ) {
-                               BackendDB               db = *be;
-
                                db.bd_info = lback;
                                db.be_private = (void *)lc->lc_cfg_li;
                                ldap_chain_db_destroy_one( &db, NULL );
                                lc->lc_cfg_li = NULL;
-
                        } else {
                                if ( lc->lc_cfg_li->li_bvuri == NULL
                                        || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] )
@@ -1836,7 +1879,7 @@ private_destroy:;
                        }
                }
        }
-       
+
        return rc;
 }
 
@@ -1944,6 +1987,11 @@ ldap_chain_db_close(
        BackendDB       *be,
        ConfigReply     *cr )
 {
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#ifdef SLAP_CONFIG_DELETE
+       overlay_unregister_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
+#endif /* SLAP_CONFIG_DELETE */
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
        return ldap_chain_db_func( be, db_close );
 }
 
@@ -2046,18 +2094,28 @@ ldap_chain_db_open_one(
 
                if ( li->li_uri == NULL ) {
                        ber_str2bv( "cn=Common Connections", 0, 1,
-                               &li->li_monitor_info.lmi_rdn );
+                               &li->li_monitor_info.lmi_conn_rdn );
+                       ber_str2bv( "cn=Operations on Common Connections", 0, 1,
+                               &li->li_monitor_info.lmi_conn_rdn );
 
                } else {
                        char            *ptr;
 
-                       li->li_monitor_info.lmi_rdn.bv_len
+                       li->li_monitor_info.lmi_conn_rdn.bv_len
                                = STRLENOF( "cn=" ) + strlen( li->li_uri );
-                       ptr = li->li_monitor_info.lmi_rdn.bv_val
-                               = ch_malloc( li->li_monitor_info.lmi_rdn.bv_len + 1 );
+                       ptr = li->li_monitor_info.lmi_conn_rdn.bv_val
+                               = ch_malloc( li->li_monitor_info.lmi_conn_rdn.bv_len + 1 );
                        ptr = lutil_strcopy( ptr, "cn=" );
                        ptr = lutil_strcopy( ptr, li->li_uri );
                        ptr[ 0 ] = '\0';
+
+                       li->li_monitor_info.lmi_ops_rdn.bv_len
+                               = STRLENOF( "cn=Operations on " ) + strlen( li->li_uri );
+                       ptr = li->li_monitor_info.lmi_ops_rdn.bv_val
+                               = ch_malloc( li->li_monitor_info.lmi_ops_rdn.bv_len + 1 );
+                       ptr = lutil_strcopy( ptr, "cn=Operations on " );
+                       ptr = lutil_strcopy( ptr, li->li_uri );
+                       ptr[ 0 ] = '\0';
                }
        }