static int slapi_op_func( Operation *op, SlapReply *rs ) { Slapi_PBlock *pb; slap_operation_t which; struct slapi_op_info *opinfo; int rc; slap_overinfo *oi; slap_overinst *on; slap_callback cb; int internal_op; int preop_type, postop_type; BackendDB *be; if ( !slapi_plugins_used ) return SLAP_CB_CONTINUE; /* * Find the SLAPI operation information for this LDAP * operation; this will contain the preop and postop * plugin types, as well as optional callbacks for * setting up the SLAPI environment. */ which = slapi_tag2op( op->o_tag ); if ( which >= op_last ) { /* invalid operation, but let someone else deal with it */ return SLAP_CB_CONTINUE; } opinfo = &slapi_op_dispatch_table[which]; if ( opinfo == NULL ) { /* no SLAPI plugin types for this operation */ return SLAP_CB_CONTINUE; } internal_op = slapi_op_internal_p( op, rs, &cb ); if ( internal_op ) { preop_type = opinfo->soi_internal_preop; postop_type = opinfo->soi_internal_postop; } else { preop_type = opinfo->soi_preop; postop_type = opinfo->soi_postop; } if ( preop_type == 0 ) { /* no SLAPI plugin types for this operation */ pb = NULL; rc = SLAP_CB_CONTINUE; goto cleanup; } pb = SLAPI_OPERATION_PBLOCK( op ); /* cache backend so we call correct postop plugins */ be = pb->pb_op->o_bd; rc = slapi_int_call_plugins( be, preop_type, pb ); /* * soi_callback is responsible for examining the result code * of the preoperation plugin and determining whether to * abort. This is needed because of special SLAPI behaviour e with bind preoperation plugins. * * The soi_callback function is also used to reset any values * returned from the preoperation plugin before calling the * backend (for the success case). */ if ( opinfo->soi_callback == NULL ) { /* default behaviour is preop plugin can abort operation */ if ( rc < 0 ) { rc = rs->sr_err; goto cleanup; } } else { rc = (opinfo->soi_callback)( op, rs, rc ); if ( rc ) goto cleanup; } /* * Call actual backend (or next overlay in stack). We need to * do this rather than returning SLAP_CB_CONTINUE and calling * postoperation plugins in a response handler to match the * behaviour of SLAPI in OpenLDAP 2.2, where postoperation * plugins are called after the backend has completely * finished processing the operation. */ on = (slap_overinst *)op->o_bd->bd_info; oi = on->on_info; rc = overlay_op_walk( op, rs, which, oi, on->on_next ); /* * Call postoperation plugins */ slapi_int_call_plugins( be, postop_type, pb ); cleanup: if ( !internal_op ) { slapi_pblock_destroy(pb); cb.sc_private = NULL; } op->o_callback = cb.sc_next; return rc; }
static int translucent_search(Operation *op, SlapReply *rs) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; translucent_info *ov = on->on_bi.bi_private; slap_callback cb = { NULL, NULL, NULL, NULL }; trans_ctx tc; Filter *fl, *fr; struct berval fbv; int rc = 0; if ( op->o_managedsait > SLAP_CONTROL_IGNORED ) return SLAP_CB_CONTINUE; Debug(LDAP_DEBUG_TRACE, "==> translucent_search: <%s> %s\n", op->o_req_dn.bv_val, op->ors_filterstr.bv_val, 0); if(ov->defer_db_open) { send_ldap_error(op, rs, LDAP_UNAVAILABLE, "remote DB not available"); return(rs->sr_err); } fr = ov->remote ? trans_filter_dup( op, op->ors_filter, ov->remote ) : NULL; fl = ov->local ? trans_filter_dup( op, op->ors_filter, ov->local ) : NULL; cb.sc_response = (slap_response *) translucent_search_cb; cb.sc_private = &tc; cb.sc_next = op->o_callback; ov->db.be_acl = op->o_bd->be_acl; tc.db = op->o_bd; tc.on = on; tc.orig = op->ors_filter; tc.list = NULL; tc.step = 0; tc.slimit = op->ors_slimit; tc.attrs = NULL; fbv = op->ors_filterstr; op->o_callback = &cb; if ( fr || !fl ) { tc.attrs = op->ors_attrs; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_all_attributes; op->o_bd = &ov->db; tc.step |= RMT_SIDE; if ( fl ) { tc.step |= USE_LIST; op->ors_filter = fr; filter2bv_x( op, fr, &op->ors_filterstr ); } rc = ov->db.bd_info->bi_op_search(op, rs); if ( op->ors_attrs == slap_anlist_all_attributes ) op->ors_attrs = tc.attrs; op->o_bd = tc.db; if ( fl ) { op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } } if ( fl && !rc ) { tc.step |= LCL_SIDE; op->ors_filter = fl; filter2bv_x( op, fl, &op->ors_filterstr ); rc = overlay_op_walk( op, rs, op_search, on->on_info, on->on_next ); op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } op->ors_filterstr = fbv; op->ors_filter = tc.orig; op->o_callback = cb.sc_next; rs->sr_attrs = op->ors_attrs; rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs ); /* Send out anything remaining on the list and finish */ if ( tc.step & USE_LIST ) { if ( tc.list ) { Avlnode *av; av = tavl_end( tc.list, TAVL_DIR_LEFT ); while ( av ) { rs->sr_entry = av->avl_data; if ( rc == LDAP_SUCCESS && LDAP_COMPARE_TRUE == test_filter( op, rs->sr_entry, op->ors_filter )) { rs->sr_flags = REP_ENTRY_MUSTBEFREED; rc = send_search_entry( op, rs ); } else { entry_free( rs->sr_entry ); } av = tavl_next( av, TAVL_DIR_RIGHT ); } tavl_free( tc.list, NULL ); rs->sr_flags = 0; rs->sr_entry = NULL; } send_ldap_result( op, rs ); } op->ors_slimit = tc.slimit; /* Free in reverse order */ if ( fl ) trans_filter_free( op, fl ); if ( fr ) trans_filter_free( op, fr ); return rc; }