+ /* If we're on the master backend, let overlay framework handle it */
+ if ( op->o_bd == b0 )
+ return SLAP_CB_CONTINUE;
+
+ b0->bd_info = on->on_info->oi_orig;
+
+ switch(op->o_tag) {
+ case LDAP_REQ_ADD: which = op_add; break;
+ case LDAP_REQ_DELETE: which = op_delete; break;
+ case LDAP_REQ_MODIFY: which = op_modify; break;
+ case LDAP_REQ_MODRDN: which = op_modrdn; break;
+ case LDAP_REQ_EXTENDED: which = op_extended; break;
+ default: assert( 0 ); break;
+ }
+
+ func = &op->o_bd->bd_info->bi_op_bind;
+ if ( func[which] )
+ rc = func[which]( op, rs );
+ else
+ rc = SLAP_CB_BYPASS;
+
+ op->o_bd = b0;
+ op->o_bd->bd_info = bi0;
+ return rc;
+}
+
+static int
+glue_response ( Operation *op, SlapReply *rs )
+{
+ BackendDB *be = op->o_bd;
+ be = glue_back_select (op->o_bd, &op->o_req_ndn);
+
+ /* If we're on the master backend, let overlay framework handle it.
+ * Otherwise, bail out.
+ */
+ return ( op->o_bd == be ) ? SLAP_CB_CONTINUE : SLAP_CB_BYPASS;
+}
+
+static int
+glue_chk_referrals ( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ BackendDB *b0 = op->o_bd;
+ BackendInfo *bi0 = op->o_bd->bd_info;
+ int rc;
+
+ op->o_bd = glue_back_select (b0, &op->o_req_ndn);
+ if ( op->o_bd == b0 )
+ return SLAP_CB_CONTINUE;
+
+ b0->bd_info = on->on_info->oi_orig;
+
+ if ( op->o_bd->bd_info->bi_chk_referrals )
+ rc = ( *op->o_bd->bd_info->bi_chk_referrals )( op, rs );
+ else
+ rc = SLAP_CB_CONTINUE;
+
+ op->o_bd = b0;
+ op->o_bd->bd_info = bi0;
+ return rc;
+}
+
+static int
+glue_chk_controls ( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ BackendDB *b0 = op->o_bd;
+ BackendInfo *bi0 = op->o_bd->bd_info;
+ int rc = SLAP_CB_CONTINUE;
+
+ op->o_bd = glue_back_select (b0, &op->o_req_ndn);
+ if ( op->o_bd == b0 )
+ return SLAP_CB_CONTINUE;
+
+ b0->bd_info = on->on_info->oi_orig;
+
+ /* if the subordinate database has overlays, the bi_chk_controls()
+ * hook is actually over_aux_chk_controls(); in case it actually
+ * wraps a missing hok, we need to mimic the behavior
+ * of the frontend applied to that database */
+ if ( op->o_bd->bd_info->bi_chk_controls ) {
+ rc = ( *op->o_bd->bd_info->bi_chk_controls )( op, rs );
+ }
+
+
+ if ( rc == SLAP_CB_CONTINUE ) {
+ rc = backend_check_controls( op, rs );
+ }
+
+ op->o_bd = b0;
+ op->o_bd->bd_info = bi0;
+ return rc;
+}
+
+/* ITS#4615 - overlays configured above the glue overlay should be
+ * invoked for the entire glued tree. Overlays configured below the
+ * glue overlay should only be invoked on the master backend.
+ * So, if we're searching on any subordinates, we need to force the
+ * current overlay chain to stop processing, without stopping the
+ * overall callback flow.
+ */
+static int
+glue_sub_search( Operation *op, SlapReply *rs, BackendDB *b0,
+ slap_overinst *on )
+{
+ /* Process any overlays on the master backend */
+ if ( op->o_bd == b0 && on->on_next ) {
+ BackendInfo *bi = op->o_bd->bd_info;
+ int rc = SLAP_CB_CONTINUE;
+ for ( on=on->on_next; on; on=on->on_next ) {
+ op->o_bd->bd_info = (BackendInfo *)on;
+ if ( on->on_bi.bi_op_search ) {
+ rc = on->on_bi.bi_op_search( op, rs );
+ if ( rc != SLAP_CB_CONTINUE )
+ break;
+ }
+ }
+ op->o_bd->bd_info = bi;
+ if ( rc != SLAP_CB_CONTINUE )
+ return rc;
+ }
+ return op->o_bd->be_search( op, rs );
+}
+
+static int
+glue_op_search ( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+ BackendDB *b0 = op->o_bd;
+ BackendDB *b1 = NULL, *btmp;
+ BackendInfo *bi0 = op->o_bd->bd_info;
+ int i;
+ long stoptime = 0, starttime;
+ glue_state gs = {NULL, NULL, NULL, 0, 0, 0, 0};
+ slap_callback cb = { NULL, glue_op_response, glue_op_cleanup, NULL };
+ int scope0, tlimit0;
+ struct berval dn, ndn, *pdn;