X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fsearch.c;h=046efa547130539124af21f77278c5736729e190;hb=c754980045a81e1a63d4c083c1dcf9d956163739;hp=f72f0c6ea2e94b8ac112ca65012aaccc9e438cbb;hpb=c04e9ac9932961ff54fe59f352919d417c49ab7c;p=openldap diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index f72f0c6ea2..046efa5471 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -19,96 +19,394 @@ static int base_candidate( Entry *e, ID *ids ); static int search_candidates( - BackendDB *be, - Operation *op, + Operation *stackop, /* op with the current threadctx/slab cache */ + Operation *sop, /* search op */ + SlapReply *rs, Entry *e, - Filter *filter, - int scope, - int deref, - ID *ids ); + u_int32_t locker, + ID *ids, + ID *scopes ); static void send_pagerequest_response( - Connection *conn, Operation *op, + SlapReply *rs, ID lastid, - int nentries, - int tentries ); + int tentries ); + +/* Dereference aliases for a single alias entry. Return the final + * dereferenced entry on success, NULL on any failure. + */ +static Entry * deref_base ( + Operation *op, + SlapReply *rs, + Entry *e, + Entry **matched, + u_int32_t locker, + DB_LOCK *lock, + ID *tmp, + ID *visited ) +{ + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + struct berval ndn; + EntryInfo *ei; + DB_LOCK lockr; + + rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM; + rs->sr_text = "maximum deref depth exceeded"; + + while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) { + + /* Remember the last entry we looked at, so we can + * report broken links + */ + *matched = e; + + /* If this is part of a subtree or onelevel search, + * have we seen this ID before? If so, quit. + */ + if ( visited && bdb_idl_insert( visited, e->e_id ) ) { + e = NULL; + break; + } + + /* If we've seen this ID during this deref iteration, + * we've hit a loop. + */ + if ( bdb_idl_insert( tmp, e->e_id ) ) { + rs->sr_err = LDAP_ALIAS_PROBLEM; + rs->sr_text = "circular alias"; + e = NULL; + break; + } + + /* If there was a problem getting the aliasedObjectName, + * get_alias_dn will have set the error status. + */ + if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) { + e = NULL; + break; + } + + rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &ndn, &ei, + 0, locker, &lockr, op->o_tmpmemctx ); + + if ( ei ) e = ei->bei_e; + else e = NULL; + + if (!e) { + rs->sr_err = LDAP_ALIAS_PROBLEM; + rs->sr_text = "aliasedObject not found"; + break; + } + + /* Free the previous entry, continue to work with the + * one we just retrieved. + */ + bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, + *matched, lock); + *lock = lockr; + + /* We found a regular entry. Return this to the caller. The + * entry is still locked for Read. + */ + if (!is_entry_alias(e)) { + rs->sr_err = LDAP_SUCCESS; + rs->sr_text = NULL; + break; + } + } + return e; +} + +/* Look for and dereference all aliases within the search scope. Adds + * the dereferenced entries to the "ids" list. Requires "stack" to be + * able to hold 8 levels of DB_SIZE IDLs. + */ +static int search_aliases( + Operation *op, + SlapReply *rs, + Entry *e, + u_int32_t locker, + Filter *sf, + ID *ids, + ID *scopes, + ID *stack +) +{ + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp; + ID cursora, ida, cursoro, ido, *subscop2; + Entry *matched, *a; + EntryInfo *ei; + struct berval bv_alias = { sizeof("alias")-1, "alias" }; + AttributeAssertion aa_alias; + Filter af; + DB_LOCK locka, lockr; + int first = 1; + + + aliases = stack; /* IDL of all aliases in the database */ + curscop = aliases + BDB_IDL_DB_SIZE; /* Aliases in the current scope */ + subscop = curscop + BDB_IDL_DB_SIZE; /* The current scope */ + visited = subscop + BDB_IDL_DB_SIZE; /* IDs we've seen in this search */ + newsubs = visited + BDB_IDL_DB_SIZE; /* New subtrees we've added */ + oldsubs = newsubs + BDB_IDL_DB_SIZE; /* Subtrees added previously */ + tmp = oldsubs + BDB_IDL_DB_SIZE; /* Scratch space for deref_base() */ + + /* A copy of subscop, because subscop gets clobbered by + * the bdb_idl_union/intersection routines + */ + subscop2 = tmp + BDB_IDL_DB_SIZE; + + 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 = NULL; + + /* Find all aliases in database */ + BDB_IDL_ALL( bdb, aliases ); + rs->sr_err = bdb_filter_candidates( op, &af, aliases, + curscop, visited ); + if (rs->sr_err != LDAP_SUCCESS) { + return rs->sr_err; + } + oldsubs[0] = 1; + oldsubs[1] = e->e_id; + + BDB_IDL_ZERO( ids ); + BDB_IDL_ZERO( visited ); + BDB_IDL_ZERO( newsubs ); + + cursoro = 0; + ido = bdb_idl_first( oldsubs, &cursoro ); + + for (;;) { + /* Set curscop to only the aliases in the current scope. Start with + * all the aliases, obtain the IDL for the current scope, and then + * get the intersection of these two IDLs. Add the current scope + * to the cumulative list of candidates. + */ + BDB_IDL_CPY( curscop, aliases ); + rs->sr_err = bdb_filter_candidates( op, sf, subscop, NULL, NULL ); + if (first) { + first = 0; + } else { + bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &locka); + } + BDB_IDL_CPY(subscop2, subscop); + rs->sr_err = bdb_idl_intersection(curscop, subscop); + bdb_idl_union( ids, subscop2 ); + + /* Dereference all of the aliases in the current scope. */ + cursora = 0; + for (ida = bdb_idl_first(curscop, &cursora); ida != NOID; + ida = bdb_idl_next(curscop, &cursora)) + { + ei = NULL; + rs->sr_err = bdb_cache_find_entry_id(op->o_bd, NULL, + ida, &ei, 0, locker, &lockr, op->o_tmpmemctx ); + if (rs->sr_err != LDAP_SUCCESS) { + continue; + } + a = ei->bei_e; + + /* This should only happen if the curscop IDL has maxed out and + * turned into a range that spans IDs indiscriminately + */ + if (!is_entry_alias(a)) { + bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, + a, &lockr); + continue; + } + + /* Actually dereference the alias */ + BDB_IDL_ZERO(tmp); + a = deref_base( op, rs, a, &matched, locker, &lockr, + tmp, visited ); + if (a) { + /* If the target was not already in our current candidates, + * make note of it in the newsubs list. Also + * set it in the scopes list so that bdb_search + * can check it. + */ + if (bdb_idl_insert(ids, a->e_id) == 0) { + bdb_idl_insert(newsubs, a->e_id); + bdb_idl_insert(scopes, a->e_id); + } + bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, + a, &lockr); + + } else if (matched) { + /* Alias could not be dereferenced, or it deref'd to + * an ID we've already seen. Ignore it. + */ + bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, + matched, &lockr ); + rs->sr_text = NULL; + } + } + /* If this is a OneLevel search, we're done; oldsubs only had one + * ID in it. For a Subtree search, oldsubs may be a list of scope IDs. + */ + if (op->ors_scope != LDAP_SCOPE_SUBTREE) break; +nextido: + ido = bdb_idl_next( oldsubs, &cursoro ); + + /* If we're done processing the old scopes, did we add any new + * scopes in this iteration? If so, go back and do those now. + */ + if (ido == NOID) { + if (BDB_IDL_IS_ZERO(newsubs)) break; + BDB_IDL_CPY(oldsubs, newsubs); + BDB_IDL_ZERO(newsubs); + cursoro = 0; + ido = bdb_idl_first( oldsubs, &cursoro ); + } + + /* Find the entry corresponding to the next scope. If it can't + * be found, ignore it and move on. This should never happen; + * we should never see the ID of an entry that doesn't exist. + * Set the name so that the scope's IDL can be retrieved. + */ + ei = NULL; + rs->sr_err = bdb_cache_find_entry_id(op->o_bd, NULL, ido, &ei, + 0, locker, &locka, op->o_tmpmemctx ); + if (rs->sr_err != LDAP_SUCCESS) goto nextido; + e = ei->bei_e; + sf->f_dn = &e->e_nname; + } + return rs->sr_err; +} + +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) +#define IS_BDB_REPLACE(type) (( type == LDAP_PSEARCH_BY_DELETE ) || \ + ( type == LDAP_PSEARCH_BY_SCOPEOUT )) +#define IS_PSEARCH (op != sop) int -bdb_search( - BackendDB *be, - Connection *conn, - Operation *op, - struct berval *base, - struct berval *nbase, - int scope, - int deref, - int slimit, - int tlimit, - Filter *filter, - struct berval *filterstr, - AttributeName *attrs, - int attrsonly ) +bdb_abandon( Operation *op, SlapReply *rs ) { - struct bdb_info *bdb = (struct bdb_info *) be->be_private; - int rc; - const char *text = NULL; + Operation *ps_list; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + + LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { + if ( ps_list->o_connid == op->o_connid ) { + if ( ps_list->o_msgid == op->oq_abandon.rs_msgid ) { + ps_list->o_abandon = 1; + LDAP_LIST_REMOVE( ps_list, o_ps_link ); + slap_op_free ( ps_list ); + return LDAP_SUCCESS; + } + } + } + return LDAP_UNAVAILABLE; +} + +int +bdb_cancel( Operation *op, SlapReply *rs ) +{ + Operation *ps_list; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + + LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { + if ( ps_list->o_connid == op->o_connid ) { + if ( ps_list->o_msgid == op->oq_cancel.rs_msgid ) { + ps_list->o_cancel = SLAP_CANCEL_DONE; + LDAP_LIST_REMOVE( ps_list, o_ps_link ); + +#if 0 + bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls, + 1, &latest_entrycsn_bv ); + send_ldap_result( conn, ps_list, LDAP_CANCELLED, + NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries); +#endif + rs->sr_err = LDAP_CANCELLED; + send_ldap_result( ps_list, rs ); + + slap_op_free ( ps_list ); + return LDAP_SUCCESS; + } + } + } + return LDAP_UNAVAILABLE; +} + +int bdb_search( Operation *op, SlapReply *rs ) +{ + return bdb_do_search( op, rs, op, NULL, 0 ); +} + +/* For persistent searches, op is the currently executing operation, + * sop is the persistent search. For regular searches, sop = op. + */ +int +bdb_do_search( Operation *op, SlapReply *rs, Operation *sop, + Entry *ps_e, int ps_type ) +#else +#define IS_PSEARCH 0 +#define sop op +int bdb_search( Operation *op, SlapReply *rs ) +#endif +{ + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; time_t stoptime; ID id, cursor; ID candidates[BDB_IDL_UM_SIZE]; - Entry *e = NULL; - BerVarray v2refs = NULL; + ID scopes[BDB_IDL_DB_SIZE]; + Entry *e = NULL, base; Entry *matched = NULL; + EntryInfo *ei; struct berval realbase = { 0, NULL }; - int nentries = 0; int manageDSAit; int tentries = 0; ID lastid = NOID; + AttributeName *attrs; #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) Filter cookief, csnfnot, csnfeq, csnfand, csnfge; AttributeAssertion aa_ge, aa_eq; int entry_count = 0; +#if 0 + struct berval entrycsn_bv = { 0, NULL }; +#endif struct berval latest_entrycsn_bv = { 0, NULL }; LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS]; int num_ctrls = 0; -#endif - + AttributeName uuid_attr[2]; #ifdef LDAP_SYNC int rc_sync = 0; - int entry_sync_state; + int entry_sync_state = -1; AttributeName null_attr; #endif - +#endif struct slap_limits_set *limit = NULL; int isroot = 0; u_int32_t locker = 0; DB_LOCK lock; - struct bdb_op_info opinfo; #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 ); + LDAP_LOG( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> bdb_back_search\n", 0, 0, 0); #endif + attrs = sop->oq_search.rs_attrs; +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) #ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) { - bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit, - tlimit, filter, filterstr, attrs, attrsonly, LDAP_CLIENT_UPDATE ); + if ( !IS_PSEARCH && sop->o_clientupdate_type & SLAP_LCUP_PERSIST ) { + sop->o_ps_protocol = LDAP_CLIENT_UPDATE; + LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link ); return LDAP_SUCCESS; } #endif -#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC) - else -#endif #ifdef LDAP_SYNC /* psearch needs to be registered before refresh begins */ /* psearch and refresh transmission is serialized in send_ldap_ber() */ - if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) { - bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit, - tlimit, filter, filterstr, attrs, attrsonly, LDAP_SYNC ); + if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_PERSIST ) { + sop->o_ps_protocol = LDAP_SYNC; + LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link ); } null_attr.an_desc = NULL; null_attr.an_oc = NULL; @@ -116,130 +414,143 @@ bdb_search( null_attr.an_name.bv_val = NULL; #endif -#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) - for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ ) + for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ ) { ctrls[num_ctrls] = NULL; + } num_ctrls = 0; -#endif + if ( IS_PSEARCH && IS_BDB_REPLACE(ps_type)) { +#ifdef LDAP_CLIENT_UPDATE + if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) { + attrs = uuid_attr; + attrs[0].an_desc = slap_schema.si_ad_entryUUID; + attrs[0].an_oc = NULL; + attrs[0].an_name = attrs[0].an_desc->ad_cname; + attrs[1].an_desc = NULL; + attrs[1].an_oc = NULL; + attrs[1].an_name.bv_len = 0; + attrs[1].an_name.bv_val = NULL; + } else +#endif +#ifdef LDAP_SYNC + if (sop->o_ps_protocol == LDAP_SYNC ) { + attrs = uuid_attr; + attrs[0].an_desc = NULL; + attrs[0].an_oc = NULL; + attrs[0].an_name.bv_len = 0; + attrs[0].an_name.bv_val = NULL; + } else +#endif + { + rs->sr_err = 1; + goto done; + } + } +#endif - manageDSAit = get_manageDSAit( op ); + manageDSAit = get_manageDSAit( sop ); - rc = LOCK_ID (bdb->bi_dbenv, &locker ); + rs->sr_err = LOCK_ID (bdb->bi_dbenv, &locker ); - switch(rc) { + switch(rs->sr_err) { case 0: break; default: - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); - return rc; + send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); + return rs->sr_err; } - opinfo.boi_bdb = be; - opinfo.boi_txn = NULL; - opinfo.boi_locker = locker; - opinfo.boi_err = 0; - op->o_private = &opinfo; - - if ( nbase->bv_len == 0 ) { + if ( sop->o_req_ndn.bv_len == 0 ) { /* DIT root special case */ e = (Entry *) &slap_entry_root; - rc = 0; - } else -#ifdef BDB_ALIASES - /* get entry with reader lock */ - if ( deref & LDAP_DEREF_FINDING ) { - e = deref_dn_r( be, nbase-, &err, &matched, &text ); - - } else -#endif - { + rs->sr_err = 0; + } else { dn2entry_retry: - rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock ); + /* get entry with reader lock */ + rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &sop->o_req_ndn, &ei, + 1, locker, &lock, op->o_tmpmemctx ); } - switch(rc) { + switch(rs->sr_err) { case DB_NOTFOUND: + matched = ei->bei_e; break; case 0: - break; + e = ei->bei_e; break; case LDAP_BUSY: - if (e != NULL) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); - } - if (matched != NULL) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock); - } - send_ldap_result( conn, op, LDAP_BUSY, - NULL, "ldap server busy", NULL, NULL ); + send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" ); LOCK_ID_FREE (bdb->bi_dbenv, locker ); return LDAP_BUSY; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; default: - if (e != NULL) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); - } - if (matched != NULL) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock); - } - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); LOCK_ID_FREE (bdb->bi_dbenv, locker ); - return rc; + return rs->sr_err; + } + + if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) { + BDB_IDL_ZERO(candidates); + e = deref_base( op, rs, e, &matched, locker, &lock, + candidates, NULL ); } if ( e == NULL ) { struct berval matched_dn = { 0, NULL }; - BerVarray refs = NULL; if ( matched != NULL ) { BerVarray erefs; ber_dupbv( &matched_dn, &matched->e_name ); erefs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) + ? get_entry_referrals( op, matched ) : NULL; - bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock); + bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, + matched, &lock); matched = NULL; if( erefs ) { - refs = referral_rewrite( erefs, &matched_dn, - base, scope ); + rs->sr_ref = referral_rewrite( erefs, &matched_dn, + &sop->o_req_dn, sop->oq_search.rs_scope ); ber_bvarray_free( erefs ); } } else { - refs = referral_rewrite( default_referral, - NULL, base, scope ); + rs->sr_ref = referral_rewrite( default_referral, + NULL, &sop->o_req_dn, sop->oq_search.rs_scope ); } - send_ldap_result( conn, op, rc=LDAP_REFERRAL , - matched_dn.bv_val, text, refs, NULL ); + rs->sr_err=LDAP_REFERRAL; + rs->sr_matched = matched_dn.bv_val; + send_ldap_result( sop, rs ); LOCK_ID_FREE (bdb->bi_dbenv, locker ); - if ( refs ) ber_bvarray_free( refs ); - if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val ); - return rc; + if ( rs->sr_ref ) { + ber_bvarray_free( rs->sr_ref ); + rs->sr_ref = NULL; + } + if ( matched_dn.bv_val ) { + ber_memfree( matched_dn.bv_val ); + rs->sr_matched = NULL; + } + return rs->sr_err; } if (!manageDSAit && e != &slap_entry_root && is_entry_referral( e ) ) { /* entry is a referral, don't allow add */ struct berval matched_dn; - BerVarray erefs, refs; + BerVarray erefs; ber_dupbv( &matched_dn, &e->e_name ); - erefs = get_entry_referrals( be, conn, op, e ); - refs = NULL; + erefs = get_entry_referrals( op, e ); bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); e = NULL; if( erefs ) { - refs = referral_rewrite( erefs, &matched_dn, - base, scope ); + rs->sr_ref = referral_rewrite( erefs, &matched_dn, + &sop->o_req_dn, sop->oq_search.rs_scope ); ber_bvarray_free( erefs ); } @@ -251,22 +562,24 @@ dn2entry_retry: 0, 0, 0 ); #endif - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn.bv_val, - refs ? NULL : "bad referral object", - refs, NULL ); + if (!rs->sr_ref) rs->sr_text = "bad_referral object"; + rs->sr_err = LDAP_REFERRAL; + rs->sr_matched = matched_dn.bv_val; + send_ldap_result( sop, rs ); LOCK_ID_FREE (bdb->bi_dbenv, locker ); - ber_bvarray_free( refs ); + ber_bvarray_free( rs->sr_ref ); + rs->sr_ref = NULL; ber_memfree( matched_dn.bv_val ); + rs->sr_matched = NULL; return 1; } /* if not root, get appropriate limits */ - if ( be_isroot( be, &op->o_ndn ) ) { + if ( be_isroot( op->o_bd, &sop->o_ndn ) ) { isroot = 1; } else { - ( void ) get_limits( be, &op->o_ndn, &limit ); + ( void ) get_limits( op->o_bd, &sop->o_ndn, &limit ); } /* The time/size limits come first because they require very little @@ -275,33 +588,32 @@ dn2entry_retry: /* if no time limit requested, use soft limit (unless root!) */ if ( isroot ) { - if ( tlimit == 0 ) { - tlimit = -1; /* allow root to set no limit */ + if ( sop->oq_search.rs_tlimit == 0 ) { + sop->oq_search.rs_tlimit = -1; /* allow root to set no limit */ } - if ( slimit == 0 ) { - slimit = -1; + if ( sop->oq_search.rs_slimit == 0 ) { + sop->oq_search.rs_slimit = -1; } } else { /* if no limit is required, use soft limit */ - if ( tlimit <= 0 ) { - tlimit = limit->lms_t_soft; + if ( sop->oq_search.rs_tlimit <= 0 ) { + sop->oq_search.rs_tlimit = limit->lms_t_soft; /* if requested limit higher than hard limit, abort */ - } else if ( tlimit > limit->lms_t_hard ) { + } else if ( sop->oq_search.rs_tlimit > limit->lms_t_hard ) { /* no hard limit means use soft instead */ if ( limit->lms_t_hard == 0 && limit->lms_t_soft > -1 - && tlimit > limit->lms_t_soft ) { - tlimit = limit->lms_t_soft; + && sop->oq_search.rs_tlimit > limit->lms_t_soft ) { + sop->oq_search.rs_tlimit = limit->lms_t_soft; /* positive hard limit means abort */ } else if ( limit->lms_t_hard > 0 ) { - send_search_result( conn, op, - LDAP_ADMINLIMIT_EXCEEDED, - NULL, NULL, NULL, NULL, 0 ); - rc = 0; + rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; + send_ldap_result( sop, rs ); + rs->sr_err = 0; goto done; } @@ -309,27 +621,26 @@ dn2entry_retry: } /* if no limit is required, use soft limit */ - if ( slimit <= 0 ) { - if ( get_pagedresults(op) && limit->lms_s_pr != 0 ) { - slimit = limit->lms_s_pr; + if ( sop->oq_search.rs_slimit <= 0 ) { + if ( get_pagedresults(sop) && limit->lms_s_pr != 0 ) { + sop->oq_search.rs_slimit = limit->lms_s_pr; } else { - slimit = limit->lms_s_soft; + sop->oq_search.rs_slimit = limit->lms_s_soft; } /* if requested limit higher than hard limit, abort */ - } else if ( slimit > limit->lms_s_hard ) { + } else if ( sop->oq_search.rs_slimit > limit->lms_s_hard ) { /* no hard limit means use soft instead */ if ( limit->lms_s_hard == 0 && limit->lms_s_soft > -1 - && slimit > limit->lms_s_soft ) { - slimit = limit->lms_s_soft; + && sop->oq_search.rs_slimit > limit->lms_s_soft ) { + sop->oq_search.rs_slimit = limit->lms_s_soft; /* positive hard limit means abort */ } else if ( limit->lms_s_hard > 0 ) { - send_search_result( conn, op, - LDAP_ADMINLIMIT_EXCEEDED, - NULL, NULL, NULL, NULL, 0 ); - rc = 0; + rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; + send_ldap_result( sop, rs ); + rs->sr_err = 0; goto done; } @@ -338,29 +649,54 @@ dn2entry_retry: } /* compute it anyway; root does not use it */ - stoptime = op->o_time + tlimit; + stoptime = op->o_time + sop->oq_search.rs_tlimit; + + /* need normalized dn below */ + ber_dupbv( &realbase, &e->e_nname ); + + /* Copy info to base, must free entry before accessing the database + * in search_candidates, to avoid deadlocks. + */ + base.e_nname = realbase; + base.e_id = e->e_id; + + if ( e != &slap_entry_root ) { + bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); + } + e = NULL; /* select candidates */ - if ( scope == LDAP_SCOPE_BASE ) { - rc = base_candidate( be, e, candidates ); + if ( sop->oq_search.rs_scope == LDAP_SCOPE_BASE ) { + rs->sr_err = base_candidate( op->o_bd, &base, candidates ); } else { BDB_IDL_ALL( bdb, candidates ); - rc = search_candidates( be, op, e, filter, - scope, deref, candidates ); + BDB_IDL_ZERO( scopes ); + rs->sr_err = search_candidates( op, sop, rs, &base, locker, candidates, scopes ); } - /* need normalized dn below */ - ber_dupbv( &realbase, &e->e_nname ); - /* start cursor at beginning of candidates. */ cursor = 0; - - if ( e != &slap_entry_root ) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if (IS_PSEARCH) { + if ( !BDB_IDL_IS_RANGE( candidates ) ) { + cursor = bdb_idl_search( candidates, ps_e->e_id ); + if ( candidates[cursor] != ps_e->e_id ) { + rs->sr_err = LDAP_SUCCESS; + goto done; + } + } else { + if ( ps_e->e_id < BDB_IDL_RANGE_FIRST(candidates) + || ps_e->e_id > BDB_IDL_RANGE_LAST(candidates)){ + rs->sr_err = LDAP_SUCCESS; + goto done; + } + } + candidates[0] = 1; + candidates[1] = ps_e->e_id; } - e = NULL; +#endif if ( candidates[0] == 0 ) { #ifdef NEW_LOGGING @@ -371,21 +707,18 @@ dn2entry_retry: 0, 0, 0 ); #endif - send_search_result( conn, op, - LDAP_SUCCESS, - NULL, NULL, NULL, NULL, 0 ); - - rc = 1; + rs->sr_err = LDAP_SUCCESS; + send_ldap_result( sop, rs ); + rs->sr_err = 1; goto done; } /* if not root and candidates exceed to-be-checked entries, abort */ if ( !isroot && limit->lms_s_unchecked != -1 ) { if ( BDB_IDL_N(candidates) > (unsigned) limit->lms_s_unchecked ) { - send_search_result( conn, op, - LDAP_ADMINLIMIT_EXCEEDED, - NULL, NULL, NULL, NULL, 0 ); - rc = 1; + rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; + send_ldap_result( sop, rs ); + rs->sr_err = 1; goto done; } } @@ -395,18 +728,18 @@ dn2entry_retry: } #ifdef LDAP_CONTROL_PAGEDRESULTS - if ( get_pagedresults(op) ) { - if ( op->o_pagedresults_state.ps_cookie == 0 ) { + if ( get_pagedresults(sop) ) { + if ( sop->o_pagedresults_state.ps_cookie == 0 ) { id = 0; } else { - if ( op->o_pagedresults_size == 0 ) { - send_search_result( conn, op, LDAP_SUCCESS, - NULL, "search abandoned by pagedResult size=0", - NULL, NULL, 0); + if ( sop->o_pagedresults_size == 0 ) { + rs->sr_err = LDAP_SUCCESS; + rs->sr_text = "search abandoned by pagedResult size=0"; + send_ldap_result( sop, rs ); goto done; } for ( id = bdb_idl_first( candidates, &cursor ); - id != NOID && id <= (ID)( op->o_pagedresults_state.ps_cookie ); + id != NOID && id <= (ID)( sop->o_pagedresults_state.ps_cookie ); id = bdb_idl_next( candidates, &cursor ) ); } if ( cursor == NOID ) { @@ -419,9 +752,9 @@ dn2entry_retry: "bdb_search: no paged results candidates\n", 0, 0, 0 ); #endif - send_pagerequest_response( conn, op, lastid, 0, 0 ); + send_pagerequest_response( sop, rs, lastid, 0 ); - rc = 1; + rs->sr_err = 1; goto done; } goto loop_begin; @@ -429,7 +762,9 @@ dn2entry_retry: #endif #ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { + if ( (sop->o_clientupdate_type & SLAP_LCUP_SYNC) || + (IS_PSEARCH && sop->o_ps_protocol == LDAP_CLIENT_UPDATE )) + { cookief.f_choice = LDAP_FILTER_AND; cookief.f_and = &csnfnot; cookief.f_next = NULL; @@ -441,7 +776,7 @@ dn2entry_retry: csnfeq.f_choice = LDAP_FILTER_EQUALITY; csnfeq.f_ava = &aa_eq; csnfeq.f_av_desc = slap_schema.si_ad_entryCSN; - ber_dupbv( &csnfeq.f_av_value, &op->o_clientupdate_state ); + csnfeq.f_av_value = sop->o_clientupdate_state; csnfand.f_choice = LDAP_FILTER_AND; csnfand.f_and = &csnfge; @@ -450,15 +785,17 @@ dn2entry_retry: csnfge.f_choice = LDAP_FILTER_GE; csnfge.f_ava = &aa_ge; csnfge.f_av_desc = slap_schema.si_ad_entryCSN; - ber_dupbv( &csnfge.f_av_value, &op->o_clientupdate_state ); - csnfge.f_next = filter; + csnfge.f_av_value = sop->o_clientupdate_state; + csnfge.f_next = sop->oq_search.rs_filter; } #endif #if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC) else #endif #ifdef LDAP_SYNC - if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) { + if ( (sop->o_sync_mode & SLAP_SYNC_REFRESH) || + ( IS_PSEARCH && sop->o_ps_protocol == LDAP_SYNC )) + { cookief.f_choice = LDAP_FILTER_AND; cookief.f_and = &csnfnot; cookief.f_next = NULL; @@ -470,7 +807,7 @@ dn2entry_retry: csnfeq.f_choice = LDAP_FILTER_EQUALITY; csnfeq.f_ava = &aa_eq; csnfeq.f_av_desc = slap_schema.si_ad_entryCSN; - ber_dupbv( &csnfeq.f_av_value, &op->o_sync_state ); + csnfeq.f_av_value = sop->o_sync_state; csnfand.f_choice = LDAP_FILTER_AND; csnfand.f_and = &csnfge; @@ -479,8 +816,8 @@ dn2entry_retry: csnfge.f_choice = LDAP_FILTER_GE; csnfge.f_ava = &aa_ge; csnfge.f_av_desc = slap_schema.si_ad_entryCSN; - ber_dupbv( &csnfge.f_av_value, &op->o_sync_state ); - csnfge.f_next = filter; + csnfge.f_av_value = sop->o_sync_state; + csnfge.f_next = sop->oq_search.rs_filter; } #endif @@ -488,331 +825,453 @@ dn2entry_retry: id != NOID; id = bdb_idl_next( candidates, &cursor ) ) { - int scopeok = 0; loop_begin: /* check for abandon */ - if ( op->o_abandon ) { - rc = 0; + if ( sop->o_abandon ) { + rs->sr_err = 0; goto done; } #ifdef LDAP_EXOP_X_CANCEL - if ( op->o_cancel ) { - assert( op->o_cancel == LDAP_CANCEL_REQ ); - rc = 0; - send_search_result( conn, op, LDAP_CANCELLED, - NULL, NULL, NULL, NULL, 0 ); - op->o_cancel = LDAP_CANCEL_ACK; + if ( sop->o_cancel ) { + assert( sop->o_cancel == SLAP_CANCEL_REQ ); + rs->sr_err = LDAP_CANCELLED; + send_ldap_result( sop, rs ); + sop->o_cancel = SLAP_CANCEL_ACK; + rs->sr_err = 0; goto done; } #endif /* check time limit */ - if ( tlimit != -1 && slap_get_time() > stoptime ) { - send_search_result( conn, op, rc = LDAP_TIMELIMIT_EXCEEDED, - NULL, NULL, v2refs, NULL, nentries ); + if ( sop->oq_search.rs_tlimit != -1 && slap_get_time() > stoptime ) { + rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; + rs->sr_ref = rs->sr_v2ref; + send_ldap_result( sop, rs ); goto done; } + +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if (!IS_PSEARCH) { +#endif id2entry_retry: - /* get the entry with reader lock */ - rc = bdb_id2entry_r( be, NULL, id, &e, locker, &lock ); + /* get the entry with reader lock */ + ei = NULL; + rs->sr_err = bdb_cache_find_entry_id( op->o_bd, NULL, + id, &ei, 0, locker, &lock, op->o_tmpmemctx ); + + if (rs->sr_err == LDAP_BUSY) { + rs->sr_text = "ldap server busy"; + send_ldap_result( sop, rs ); + goto done; - if (rc == LDAP_BUSY) { - send_ldap_result( conn, op, rc=LDAP_BUSY, - NULL, "ldap server busy", NULL, NULL ); - goto done; + } else if ( rs->sr_err == DB_LOCK_DEADLOCK + || rs->sr_err == DB_LOCK_NOTGRANTED ) + { + goto id2entry_retry; + } - } else if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) { - goto id2entry_retry; - } + if ( ei && rs->sr_err == 0 ) { + e = ei->bei_e; + } else { + e = NULL; + } - if ( e == NULL ) { - if( !BDB_IDL_IS_RANGE(candidates) ) { - /* only complain for non-range IDLs */ + if ( e == NULL ) { + if( !BDB_IDL_IS_RANGE(candidates) ) { + /* only complain for non-range IDLs */ #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, - "bdb_search: candidate %ld not found\n", (long) id, 0, 0); + LDAP_LOG ( OPERATION, RESULTS, + "bdb_search: candidate %ld not found\n", + (long) id, 0, 0); #else - Debug( LDAP_DEBUG_TRACE, - "bdb_search: candidate %ld not found\n", - (long) id, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + "bdb_search: candidate %ld not found\n", + (long) id, 0, 0 ); #endif - } + } - goto loop_continue; + goto loop_continue; + } +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + } else { + e = ps_e; } +#endif + rs->sr_entry = e; #ifdef BDB_SUBENTRIES if ( is_entry_subentry( e ) ) { - if( scope != LDAP_SCOPE_BASE ) { - if(!get_subentries_visibility( op )) { + if( sop->oq_search.rs_scope != LDAP_SCOPE_BASE ) { + if(!get_subentries_visibility( sop )) { /* only subentries are visible */ goto loop_continue; } - } else if ( get_subentries( op ) && - !get_subentries_visibility( op )) + } else if ( get_subentries( sop ) && + !get_subentries_visibility( sop )) { /* only subentries are visible */ goto loop_continue; } - } else if ( get_subentries_visibility( op )) { + } else if ( get_subentries_visibility( sop )) { /* only subentries are visible */ goto loop_continue; } #endif -#ifdef BDB_ALIASES - if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) { - Entry *matched; - int err; - const char *text; - - e = deref_entry_r( be, e, &err, &matched, &text ); - - if( e == NULL ) { - e = matched; - goto loop_continue; - } + /* Does this candidate actually satisfy the search scope? + * + * Note that we don't lock access to the bei_parent pointer. + * Since only leaf nodes can be deleted, the parent of any + * node will always be a valid node. Also since we have + * a Read lock on the data, it cannot be renamed out of the + * scope while we are looking at it, and unless we're using + * BDB_HIER, its parents cannot be moved either. + */ + switch( op->ors_scope ) { + case LDAP_SCOPE_BASE: + /* This is always true, yes? */ + if ( id == base.e_id ) + scopeok = 1; + break; + case LDAP_SCOPE_ONELEVEL: + if ( ei->bei_parent->bei_id == base.e_id ) + scopeok = 1; + break; + case LDAP_SCOPE_SUBTREE: + { EntryInfo *tmp; + for ( tmp = BEI(e); tmp->bei_parent; + tmp = tmp->bei_parent ) { + if ( tmp->bei_id == base.e_id ) { + scopeok = 1; + break; + } + } } + break; + } - if( e->e_id == id ) { - /* circular loop */ +#ifdef BDB_ALIASES + /* aliases were already dereferenced in candidate list */ + if ( sop->ors_deref & LDAP_DEREF_SEARCHING ) { + /* but if the search base is an alias, and we didn't + * deref it when finding, return it. + */ + if ( is_entry_alias(e) && + ((sop->ors_deref & LDAP_DEREF_FINDING) + || !bvmatch(&e->e_nname, &op->o_req_ndn))) + { goto loop_continue; } - /* need to skip alias which deref into scope */ - if( scope & LDAP_SCOPE_ONELEVEL ) { - struct berval pdn; - - dnParent( &e->e_nname, &pdn ): - if ( ber_bvcmp( pdn, &realbase ) ) { - goto loop_continue; + /* scopes is only non-empty for onelevel or subtree */ + if ( !scopeok && BDB_IDL_N(scopes) ) { + unsigned x; + if ( sop->ors_scope == LDAP_SCOPE_ONELEVEL ) { + x = bdb_idl_search( scopes, + e->e_id ); + if ( scopes[x] == e->e_id ) + scopeok = 1; + } else { + /* subtree, walk up the tree */ + EntryInfo *tmp = BEI(e); + for (;tmp->bei_parent; + tmp=tmp->bei_parent) { + x = bdb_idl_search( + scopes, tmp->bei_id ); + if ( scopes[x] == tmp->bei_id ) { + scopeok = 1; + break; + } + } } + } + } +#endif - } else if ( dnIsSuffix( &e->e_nname, &realbase ) ) { - /* alias is within scope */ + /* Not in scope, ignore it */ + if ( !scopeok ) { #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, - "bdb_search: \"%s\" in subtree\n", e->edn, 0, 0); + LDAP_LOG ( OPERATION, RESULTS, + "bdb_search: %ld scope not okay\n", + (long) id, 0, 0); #else - Debug( LDAP_DEBUG_TRACE, - "bdb_search: \"%s\" in subtree\n", - e->e_dn, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + "bdb_search: %ld scope not okay\n", + (long) id, 0, 0 ); #endif - goto loop_continue; - } - - scopeok = 1; + goto loop_continue; } -#endif /* * if it's a referral, add it to the list of referrals. only do * this for non-base searches, and don't check the filter * explicitly here since it's only a candidate anyway. */ - if ( !manageDSAit && scope != LDAP_SCOPE_BASE && - is_entry_referral( e ) ) + if ( !manageDSAit && sop->oq_search.rs_scope != LDAP_SCOPE_BASE + && is_entry_referral( e ) ) { - struct berval dn; - - /* check scope */ - if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) { - if ( !be_issuffix( be, &e->e_nname ) ) { - dnParent( &e->e_nname, &dn ); - scopeok = dn_match( &dn, &realbase ); - } else { - scopeok = (realbase.bv_len == 0); - } + BerVarray erefs = get_entry_referrals( sop, e ); + rs->sr_ref = referral_rewrite( erefs, + &e->e_name, NULL, + sop->oq_search.rs_scope == LDAP_SCOPE_SUBTREE + ? LDAP_SCOPE_SUBTREE + : LDAP_SCOPE_BASE ); - } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) { - scopeok = dnIsSuffix( &e->e_nname, &realbase ); + send_search_reference( sop, rs ); - } else { - scopeok = 1; - } - - if( scopeok ) { - BerVarray erefs = get_entry_referrals( - be, conn, op, e ); - BerVarray refs = referral_rewrite( erefs, - &e->e_name, NULL, - scope == LDAP_SCOPE_SUBTREE - ? LDAP_SCOPE_SUBTREE - : LDAP_SCOPE_BASE ); - - send_search_reference( be, conn, op, - e, refs, NULL, &v2refs ); - - ber_bvarray_free( refs ); - - } else { -#ifdef NEW_LOGGING - LDAP_LOG(OPERATION, DETAIL2, - "bdb_search: candidate referral %ld scope not okay\n", - id, 0, 0 ); -#else - Debug( LDAP_DEBUG_TRACE, - "bdb_search: candidate referral %ld scope not okay\n", - id, 0, 0 ); -#endif - } + ber_bvarray_free( rs->sr_ref ); + ber_bvarray_free( erefs ); + rs->sr_ref = NULL; goto loop_continue; } /* if it matches the filter and scope, send it */ +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if (IS_PSEARCH) { + if (ps_type != LDAP_PSEARCH_BY_SCOPEOUT) { + rs->sr_err = test_filter( sop, rs->sr_entry, &cookief ); + } else { + rs->sr_err = LDAP_COMPARE_TRUE; + } + } else { #ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { - rc = test_filter( be, conn, op, e, &cookief ); - } else + if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) { + rs->sr_err = test_filter( sop, rs->sr_entry, &cookief ); + } else #endif #ifdef LDAP_SYNC - if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) { - rc_sync = test_filter( be, conn, op, e, &cookief ); - rc = test_filter( be, conn, op, e, filter ); - if ( rc == LDAP_COMPARE_TRUE ) { - if ( rc_sync == LDAP_COMPARE_TRUE ) { - entry_sync_state = LDAP_SYNC_ADD; - } else { - entry_sync_state = LDAP_SYNC_PRESENT; + if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { + rc_sync = test_filter( sop, rs->sr_entry, &cookief ); + rs->sr_err = test_filter( sop, + rs->sr_entry, sop->oq_search.rs_filter ); + if ( rs->sr_err == LDAP_COMPARE_TRUE ) { + if ( rc_sync == LDAP_COMPARE_TRUE ) { + entry_sync_state = LDAP_SYNC_ADD; + } else { + entry_sync_state = LDAP_SYNC_PRESENT; + } } - } - } else + } else #endif - { - rc = test_filter( be, conn, op, e, filter ); +#endif + { + rs->sr_err = test_filter( sop, + rs->sr_entry, sop->oq_search.rs_filter ); + } +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) } +#endif - if ( rc == LDAP_COMPARE_TRUE ) { - struct berval dn; - - /* check scope */ - if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) { - if ( be_issuffix( be, &e->e_nname ) ) { - scopeok = (realbase.bv_len == 0); - } else { - dnParent( &e->e_nname, &dn ); - scopeok = dn_match( &dn, &realbase ); - } - - } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) { - scopeok = dnIsSuffix( &e->e_nname, &realbase ); - - } else { - scopeok = 1; + if ( rs->sr_err == LDAP_COMPARE_TRUE ) { + /* check size limit */ + if ( --sop->oq_search.rs_slimit == -1 ) { +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if (!IS_PSEARCH) +#endif + bdb_cache_return_entry_r( bdb->bi_dbenv, + &bdb->bi_cache, e, &lock ); + e = NULL; + rs->sr_entry = NULL; + rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + rs->sr_ref = rs->sr_v2ref; + send_ldap_result( sop, rs ); + goto done; } - if ( scopeok ) { - /* check size limit */ - if ( --slimit == -1 ) { - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e, &lock ); - e = NULL; - send_search_result( conn, op, - rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, - v2refs, NULL, nentries ); - goto done; - } - #ifdef LDAP_CONTROL_PAGEDRESULTS - if ( get_pagedresults(op) ) { - if ( nentries >= op->o_pagedresults_size ) { - send_pagerequest_response( conn, op, - lastid, nentries, tentries ); - goto done; - } - lastid = id; + if ( get_pagedresults(sop) ) { + if ( rs->sr_nentries >= sop->o_pagedresults_size ) { + send_pagerequest_response( sop, rs, + lastid, tentries ); + goto done; } + lastid = id; + } #endif - if (e) { - int result; - + if (e) { + /* safe default */ + int result = -1; + #if 0 /* noop is masked SLAP_CTRL_UPDATE */ - if( op->o_noop ) { - result = 0; - } else + if( op->o_noop ) { + result = 0; + } else +#endif +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if (IS_PSEARCH) { +#ifdef LDAP_SYNC + int premodify_found = 0; + int entry_sync_state; #endif + + if ( ps_type == LDAP_PSEARCH_BY_ADD || + ps_type == LDAP_PSEARCH_BY_DELETE || + ps_type == LDAP_PSEARCH_BY_MODIFY || + ps_type == LDAP_PSEARCH_BY_SCOPEOUT ) { + if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) { + struct psid_entry* psid_e; + LDAP_LIST_FOREACH( psid_e, + &op->o_pm_list, ps_link) + { + if( psid_e->ps_op == sop ) { +#ifdef LDAP_SYNC + premodify_found = 1; +#endif + LDAP_LIST_REMOVE(psid_e, ps_link); + break; + } + } + if (psid_e != NULL) free (psid_e); + } +#ifdef LDAP_SYNC + if ( ps_type == LDAP_PSEARCH_BY_ADD ) { + entry_sync_state = LDAP_SYNC_ADD; + } else if ( ps_type == LDAP_PSEARCH_BY_DELETE ) { + entry_sync_state = LDAP_SYNC_DELETE; + } else if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) { + if ( premodify_found ) { + entry_sync_state = LDAP_SYNC_MODIFY; + } else { + entry_sync_state = LDAP_SYNC_ADD; + } + } else if ( ps_type == LDAP_PSEARCH_BY_SCOPEOUT ) + entry_sync_state = LDAP_SYNC_DELETE; + else { + rs->sr_err = 1; + goto done; + } +#endif + #ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { - rc = bdb_build_lcup_update_ctrl( conn, op, e, ++entry_count, ctrls, - num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE ); - if ( rc != LDAP_SUCCESS ) - goto done; - result = send_search_entry( be, conn, op, - e, attrs, attrsonly, ctrls); - - if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) - ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) { + int entry_count = ++sop->o_ps_entries; + if ( IS_BDB_REPLACE(ps_type) ) { + rs->sr_err = bdb_build_lcup_update_ctrl( sop, + rs, e, entry_count, ctrls, + num_ctrls++, &latest_entrycsn_bv, + SLAP_LCUP_ENTRY_DELETED_TRUE ); + } else { + rs->sr_err = bdb_build_lcup_update_ctrl( sop, + rs, e, entry_count, ctrls, + num_ctrls++, &latest_entrycsn_bv, + SLAP_LCUP_ENTRY_DELETED_FALSE ); + } + if ( rs->sr_err != LDAP_SUCCESS ) goto done; + rs->sr_attrs = attrs; + rs->sr_ctrls = ctrls; + result = send_search_entry( sop, rs ); + ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); ch_free( ctrls[--num_ctrls] ); ctrls[num_ctrls] = NULL; + rs->sr_ctrls = NULL; } else #endif #ifdef LDAP_SYNC - if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) { - rc = bdb_build_sync_state_ctrl( conn, op, e, entry_sync_state, ctrls, - num_ctrls++, 0, &latest_entrycsn_bv ); - if ( rc != LDAP_SUCCESS ) - goto done; - - if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */ - result = send_search_entry( be, conn, op, - e, attrs, attrsonly, ctrls); - } else { /* PRESENT */ - result = send_search_entry( be, conn, op, - e, &null_attr, attrsonly, ctrls); - } - - if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) - ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + if ( sop->o_ps_protocol == LDAP_SYNC ) { + rs->sr_err = bdb_build_sync_state_ctrl( sop, + rs, e, entry_sync_state, ctrls, + num_ctrls++, 1, &latest_entrycsn_bv ); + if ( rs->sr_err != LDAP_SUCCESS ) goto done; + rs->sr_attrs = attrs; + rs->sr_ctrls = ctrls; + result = send_search_entry( sop, rs ); + ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); ch_free( ctrls[--num_ctrls] ); ctrls[num_ctrls] = NULL; + rs->sr_ctrls = NULL; } else #endif - { - result = send_search_entry( be, conn, op, - e, attrs, attrsonly, NULL); + rs->sr_err = 1; + goto done; } - } - switch (result) { - case 0: /* entry sent ok */ - nentries++; - break; - case 1: /* entry not sent */ - break; - case -1: /* connection closed */ - bdb_cache_return_entry_r(bdb->bi_dbenv, - &bdb->bi_cache, e, &lock); - e = NULL; - rc = LDAP_OTHER; - goto done; + } else if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) { + struct psid_entry* psid_e; + psid_e = (struct psid_entry *) calloc (1, + sizeof(struct psid_entry)); + psid_e->ps_op = sop; + LDAP_LIST_INSERT_HEAD( &op->o_pm_list, + psid_e, ps_link ); + + } else { + printf("Error !\n"); } - } - } else { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, - "bdb_search: %ld scope not okay\n", (long) id, 0, 0); -#else - Debug( LDAP_DEBUG_TRACE, - "bdb_search: %ld scope not okay\n", - (long) id, 0, 0 ); + } else { +#ifdef LDAP_CLIENT_UPDATE + if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) { + rs->sr_err = bdb_build_lcup_update_ctrl( sop, + rs, e, ++entry_count, ctrls, + num_ctrls++, &latest_entrycsn_bv, + SLAP_LCUP_ENTRY_DELETED_FALSE ); + if ( rs->sr_err != LDAP_SUCCESS ) goto done; + rs->sr_ctrls = ctrls; + rs->sr_attrs = sop->oq_search.rs_attrs; + result = send_search_entry( sop, rs ); + ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + ch_free( ctrls[--num_ctrls] ); + ctrls[num_ctrls] = NULL; + rs->sr_ctrls = NULL; + } else #endif +#ifdef LDAP_SYNC + if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { + rs->sr_err = bdb_build_sync_state_ctrl( sop, + rs, e, entry_sync_state, ctrls, + num_ctrls++, 0, &latest_entrycsn_bv ); + if ( rs->sr_err != LDAP_SUCCESS ) goto done; + + rs->sr_ctrls = ctrls; + if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */ + rs->sr_attrs = sop->oq_search.rs_attrs; + } else { /* PRESENT */ + rs->sr_attrs = &null_attr; + } + result = send_search_entry( sop, rs ); + ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + ch_free( ctrls[--num_ctrls] ); + ctrls[num_ctrls] = NULL; + rs->sr_ctrls = NULL; + } else +#endif +#endif + { + rs->sr_attrs = sop->oq_search.rs_attrs; + rs->sr_ctrls = NULL; + result = send_search_entry( sop, rs ); + } + } + + switch (result) { + case 0: /* entry sent ok */ + break; + case 1: /* entry not sent */ + break; + case -1: /* connection closed */ + if (!IS_PSEARCH) + bdb_cache_return_entry_r(bdb->bi_dbenv, + &bdb->bi_cache, e, &lock); + e = NULL; + rs->sr_entry = NULL; + rs->sr_err = LDAP_OTHER; + goto done; + } } } else { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, RESULTS, - "bdb_search: %ld does match filter\n", (long) id, 0, 0); + "bdb_search: %ld does not match filter\n", (long) id, 0, 0); #else Debug( LDAP_DEBUG_TRACE, - "bdb_search: %ld does match filter\n", + "bdb_search: %ld does not match filter\n", (long) id, 0, 0 ); #endif } @@ -820,46 +1279,58 @@ id2entry_retry: loop_continue: if( e != NULL ) { /* free reader lock */ - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e , &lock); + if (!IS_PSEARCH) { + bdb_cache_return_entry_r( bdb->bi_dbenv, + &bdb->bi_cache, e , &lock); + } e = NULL; + rs->sr_entry = NULL; } ldap_pvt_thread_yield(); } + if (!IS_PSEARCH) { #ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { - bdb_build_lcup_done_ctrl( conn, op, ctrls, num_ctrls++, &latest_entrycsn_bv ); + if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) { + bdb_build_lcup_done_ctrl( sop, rs, ctrls, + num_ctrls++, &latest_entrycsn_bv ); - send_search_result( conn, op, - v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, - NULL, NULL, v2refs, ctrls, nentries ); + rs->sr_ctrls = ctrls; + rs->sr_ref = rs->sr_v2ref; + rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; + send_ldap_result( sop, rs ); ch_free( latest_entrycsn_bv.bv_val ); latest_entrycsn_bv.bv_val = NULL; - if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) - ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) { + ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + } ch_free( ctrls[--num_ctrls] ); ctrls[num_ctrls] = NULL; } else #endif #ifdef LDAP_SYNC - if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) { - if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) { + if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { + if ( sop->o_sync_mode & SLAP_SYNC_PERSIST ) { /* refreshAndPersist mode */ - bdb_send_ldap_intermediate( conn, op, - LDAP_SUCCESS, NULL, NULL, NULL, LDAP_SYNC_INFO, - LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv, NULL ); + rs->sr_err = LDAP_SUCCESS; + rs->sr_rspoid = LDAP_SYNC_INFO; + rs->sr_ctrls = NULL; + bdb_send_ldap_intermediate( sop, rs, + LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv ); } else { /* refreshOnly mode */ - bdb_build_sync_done_ctrl( conn, op, ctrls, num_ctrls++, 1, &latest_entrycsn_bv ); - send_search_result( conn, op, - v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, - NULL, NULL, v2refs, ctrls, nentries ); - if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) + bdb_build_sync_done_ctrl( sop, rs, ctrls, + num_ctrls++, 1, &latest_entrycsn_bv ); + rs->sr_ctrls = ctrls; + rs->sr_ref = rs->sr_v2ref; + rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; + send_ldap_result( sop, rs ); + if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) { ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val ); + } ch_free( ctrls[--num_ctrls] ); ctrls[num_ctrls] = NULL; } @@ -869,51 +1340,30 @@ loop_continue: } else #endif { - send_search_result( conn, op, - v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, - NULL, NULL, v2refs, NULL, nentries ); + rs->sr_ctrls = NULL; + rs->sr_ref = rs->sr_v2ref; + rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; + send_ldap_result( sop, rs ); + } } - rc = 0; + rs->sr_err = LDAP_SUCCESS; done: - if( e != NULL ) { + if( !IS_PSEARCH && e != NULL ) { /* free reader lock */ bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); } -#ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { - if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) { - ch_free( csnfeq.f_av_value.bv_val ); - } - - if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) { - ch_free( csnfge.f_av_value.bv_val ); - } - } -#endif -#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) - else -#endif -#ifdef LDAP_SYNC - if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) { - if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) { - ch_free( csnfeq.f_av_value.bv_val ); - } - - if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) { - ch_free( csnfge.f_av_value.bv_val ); - } - } -#endif - LOCK_ID_FREE (bdb->bi_dbenv, locker ); - if( v2refs ) ber_bvarray_free( v2refs ); + if( rs->sr_v2ref ) { + ber_bvarray_free( rs->sr_v2ref ); + rs->sr_v2ref = NULL; + } if( realbase.bv_val ) ch_free( realbase.bv_val ); - return rc; + return rs->sr_err; } @@ -924,10 +1374,11 @@ static int base_candidate( { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, - "base_candidate: base: \"%s\" (0x%08lx)\n", e->e_dn, (long) e->e_id, 0); + "base_candidate: base: \"%s\" (0x%08lx)\n", + e->e_nname.bv_val, (long) e->e_id, 0); #else Debug(LDAP_DEBUG_ARGS, "base_candidates: base: \"%s\" (0x%08lx)\n", - e->e_dn, (long) e->e_id, 0); + e->e_nname.bv_val, (long) e->e_id, 0); #endif ids[0] = 1; @@ -975,11 +1426,10 @@ static void search_stack_free( void *key, void *data) } static void *search_stack( - BackendDB *be, Operation *op ) { - struct bdb_info *bdb = (struct bdb_info *) be->be_private; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; void *ret = NULL; if ( op->o_threadctx ) { @@ -990,7 +1440,8 @@ static void *search_stack( } if ( !ret ) { - ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE * sizeof( ID ) ); + ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE + * sizeof( ID ) ); if ( op->o_threadctx ) { ldap_pvt_thread_pool_setkey( op->o_threadctx, search_stack, ret, search_stack_free ); @@ -1002,27 +1453,23 @@ static void *search_stack( } static int search_candidates( - BackendDB *be, + Operation *stackop, Operation *op, + SlapReply *rs, Entry *e, - Filter *filter, - int scope, - int deref, - ID *ids ) + u_int32_t locker, + ID *ids, + ID *scopes ) { - struct bdb_info *bdb = (struct bdb_info *) be->be_private; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; int rc, depth = 1; - Filter f, scopef, rf, xf; + Filter f, scopef, rf, xf, nf; ID *stack; AttributeAssertion aa_ref; #ifdef BDB_SUBENTRIES Filter sf; AttributeAssertion aa_subentry; #endif -#ifdef BDB_ALIASES - Filter af; - AttributeAssertion aa_alias; -#endif /* * This routine takes as input a filter (user-filter) @@ -1034,21 +1481,23 @@ static int search_candidates( #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n", - e->e_dn, (long) e->e_id, scope); + e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope); #else Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n", - e->e_dn, (long) e->e_id, scope ); + e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope ); #endif - xf.f_or = filter; + xf.f_or = op->oq_search.rs_filter; xf.f_choice = LDAP_FILTER_OR; xf.f_next = NULL; /* If the user's filter uses objectClass=*, * these clauses are redundant. */ - if (!oc_filter(filter, 1, &depth) && !get_subentries_visibility(op) ) { + if (!oc_filter(op->oq_search.rs_filter, 1, &depth) + && !get_subentries_visibility(op) ) + { if( !get_manageDSAit(op) && !get_domainScope(op) ) { /* match referral objects */ struct berval bv_ref = { sizeof("referral")-1, "referral" }; @@ -1058,33 +1507,24 @@ static int search_candidates( rf.f_av_value = bv_ref; rf.f_next = xf.f_or; xf.f_or = &rf; + depth++; } - -#ifdef BDB_ALIASES - if( deref & LDAP_DEREF_SEARCHING ) { - /* match alias objects */ - 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 = ⁡ - } -#endif - /* We added one of these clauses, filter depth increased */ - if( xf.f_or != filter ) depth++; } - f.f_next = NULL; - f.f_choice = LDAP_FILTER_AND; - f.f_and = &scopef; - scopef.f_choice = scope == LDAP_SCOPE_SUBTREE + scopef.f_choice = op->oq_search.rs_scope == LDAP_SCOPE_SUBTREE ? SLAPD_FILTER_DN_SUBTREE : SLAPD_FILTER_DN_ONE; scopef.f_dn = &e->e_nname; - scopef.f_next = xf.f_or == filter ? filter : &xf ; - /* Filter depth increased again, adding scope clause */ + scopef.f_next = NULL; + + f.f_next = NULL; + f.f_choice = LDAP_FILTER_AND; + f.f_and = &nf; + /* Dummy; we compute scope separately now */ + nf.f_choice = LDAP_FILTER_NOT; + nf.f_next = xf.f_or == op->oq_search.rs_filter + ? op->oq_search.rs_filter : &xf ; + /* Filter depth increased again, adding dummy clause */ depth++; #ifdef BDB_SUBENTRIES @@ -1095,7 +1535,7 @@ static int search_candidates( sf.f_av_desc = slap_schema.si_ad_objectClass; sf.f_av_value = bv_subentry; sf.f_next = scopef.f_next; - scopef.f_next = &sf; + nf.f_next = &sf; } #endif @@ -1103,10 +1543,20 @@ static int search_candidates( if ( depth+1 > bdb->bi_search_stack_depth ) { stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) ); } else { - stack = search_stack( be, op ); + stack = search_stack( stackop ); + } + + if( op->ors_deref & LDAP_DEREF_SEARCHING ) { + rc = search_aliases( op, rs, e, locker, &scopef, ids, scopes, stack ); + } else { + rc = bdb_filter_candidates( op, &scopef, ids, + stack, stack+BDB_IDL_UM_SIZE ); } - rc = bdb_filter_candidates( be, &f, ids, stack, stack+BDB_IDL_UM_SIZE ); + if ( rc == LDAP_SUCCESS ) { + rc = bdb_filter_candidates( op, &f, ids, + stack, stack+BDB_IDL_UM_SIZE ); + } if ( depth+1 > bdb->bi_search_stack_depth ) { ch_free( stack ); @@ -1143,10 +1593,9 @@ static int search_candidates( #ifdef LDAP_CONTROL_PAGEDRESULTS static void send_pagerequest_response( - Connection *conn, Operation *op, + SlapReply *rs, ID lastid, - int nentries, int tentries ) { LDAPControl ctrl, *ctrls[2]; @@ -1159,10 +1608,10 @@ send_pagerequest_response( LDAP_LOG ( OPERATION, ENTRY, "send_pagerequest_response: lastid: (0x%08lx) " "nentries: (0x%081x)\n", - lastid, nentries, NULL ); + lastid, rs->sr_nentries, NULL ); #else Debug(LDAP_DEBUG_ARGS, "send_pagerequest_response: lastid: (0x%08lx) " - "nentries: (0x%081x)\n", lastid, nentries, NULL ); + "nentries: (0x%081x)\n", lastid, rs->sr_nentries, NULL ); #endif ctrl.ldctl_value.bv_val = NULL; @@ -1172,7 +1621,7 @@ send_pagerequest_response( ber_init2( ber, NULL, LBER_USE_DER ); respcookie = ( PagedResultsCookie )lastid; - conn->c_pagedresults_state.ps_cookie = respcookie; + op->o_conn->c_pagedresults_state.ps_cookie = respcookie; cookie.bv_len = sizeof( respcookie ); cookie.bv_val = (char *)&respcookie; @@ -1189,9 +1638,9 @@ send_pagerequest_response( ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ctrls[0]->ldctl_iscritical = 0; - send_search_result( conn, op, - LDAP_SUCCESS, - NULL, NULL, NULL, ctrls, nentries ); + rs->sr_ctrls = ctrls; + rs->sr_err = LDAP_SUCCESS; + send_ldap_result( op, rs ); done: (void) ber_free_buf( ber ); @@ -1201,8 +1650,8 @@ done: #ifdef LDAP_CLIENT_UPDATE int bdb_build_lcup_update_ctrl( - Connection *conn, Operation *op, + SlapReply *rs, Entry *e, int entry_count, LDAPControl **ctrls, @@ -1213,7 +1662,6 @@ bdb_build_lcup_update_ctrl( Attribute* a; int ret; int res; - int rc; const char *text = NULL; char berbuf[LBER_ELEMENT_SIZEOF]; @@ -1233,8 +1681,7 @@ bdb_build_lcup_update_ctrl( ber_dupbv( latest_entrycsn_bv, &entrycsn_bv ); } else { res = value_match( &ret, desc, - desc->ad_type->sat_ordering, - SLAP_MR_ASSERTION_SYNTAX_MATCH, + desc->ad_type->sat_ordering, 0, &entrycsn_bv, latest_entrycsn_bv, &text ); if ( res != LDAP_SUCCESS ) { ret = 0; @@ -1258,17 +1705,18 @@ bdb_build_lcup_update_ctrl( } } - if ( entry_count % op->o_clientupdate_interval == 0 ) + if ( entry_count % op->o_clientupdate_interval == 0 ) { ber_printf( ber, "{bb{sON}N}", SLAP_LCUP_STATE_UPDATE_FALSE, isdeleted, - LDAP_LCUP_COOKIE_OID, &entrycsn_bv ); - else /* Do not send cookie */ + LDAP_CUP_COOKIE_OID, &entrycsn_bv ); + } else { /* Do not send cookie */ ber_printf( ber, "{bbN}", SLAP_LCUP_STATE_UPDATE_FALSE, isdeleted ); + } ch_free( entrycsn_bv.bv_val ); entrycsn_bv.bv_val = NULL; @@ -1289,8 +1737,7 @@ bdb_build_lcup_update_ctrl( "bdb_build_lcup_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return ret; } @@ -1299,13 +1746,13 @@ bdb_build_lcup_update_ctrl( int bdb_build_lcup_done_ctrl( - Connection *conn, Operation *op, + SlapReply *rs, LDAPControl **ctrls, int num_ctrls, struct berval *latest_entrycsn_bv ) { - int ret, rc; + int ret; char berbuf[LBER_ELEMENT_SIZEOF]; BerElement *ber = (BerElement *)berbuf; @@ -1313,8 +1760,7 @@ bdb_build_lcup_done_ctrl( ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) ); - ber_printf( ber, "{sO", LDAP_LCUP_COOKIE_OID, latest_entrycsn_bv ); - ber_printf( ber, "N}" ); + ber_printf( ber, "{sON}", LDAP_CUP_COOKIE_OID, latest_entrycsn_bv ); ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE; ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate; @@ -1327,11 +1773,11 @@ bdb_build_lcup_done_ctrl( LDAP_LOG ( OPERATION, RESULTS, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", + Debug( LDAP_DEBUG_TRACE, + "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return ret; } @@ -1342,8 +1788,8 @@ bdb_build_lcup_done_ctrl( #ifdef LDAP_SYNC int bdb_build_sync_state_ctrl( - Connection *conn, Operation *op, + SlapReply *rs, Entry *e, int entry_sync_state, LDAPControl **ctrls, @@ -1354,7 +1800,6 @@ bdb_build_sync_state_ctrl( Attribute* a; int ret; int res; - int rc; const char *text = NULL; char berbuf[LBER_ELEMENT_SIZEOF]; @@ -1375,8 +1820,7 @@ bdb_build_sync_state_ctrl( ber_dupbv( latest_entrycsn_bv, &entrycsn_bv ); } else { res = value_match( &ret, desc, - desc->ad_type->sat_ordering, - SLAP_MR_ASSERTION_SYNTAX_MATCH, + desc->ad_type->sat_ordering, 0, &entrycsn_bv, latest_entrycsn_bv, &text ); if ( res != LDAP_SUCCESS ) { ret = 0; @@ -1401,10 +1845,13 @@ bdb_build_sync_state_ctrl( } } - if ( send_cookie ) - ber_printf( ber, "{eOON}", entry_sync_state, &entryuuid_bv, &entrycsn_bv ); - else - ber_printf( ber, "{eON}", entry_sync_state, &entryuuid_bv ); + if ( send_cookie ) { + ber_printf( ber, "{eOON}", + entry_sync_state, &entryuuid_bv, &entrycsn_bv ); + } else { + ber_printf( ber, "{eON}", + entry_sync_state, &entryuuid_bv ); + } ch_free( entrycsn_bv.bv_val ); entrycsn_bv.bv_val = NULL; @@ -1427,8 +1874,7 @@ bdb_build_sync_state_ctrl( "bdb_build_sync_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return ret; } @@ -1437,14 +1883,14 @@ bdb_build_sync_state_ctrl( int bdb_build_sync_done_ctrl( - Connection *conn, Operation *op, + SlapReply *rs, LDAPControl **ctrls, int num_ctrls, int send_cookie, struct berval *latest_entrycsn_bv ) { - int ret,rc; + int ret; char berbuf[LBER_ELEMENT_SIZEOF]; BerElement *ber = (BerElement *)berbuf; @@ -1467,13 +1913,14 @@ bdb_build_sync_done_ctrl( if ( ret < 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, RESULTS, - "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); + "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", + 0, 0, 0 ); #else - Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", + Debug( LDAP_DEBUG_TRACE, + "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return ret; } @@ -1482,47 +1929,44 @@ bdb_build_sync_done_ctrl( int bdb_send_ldap_intermediate( - Connection *conn, Operation *op, - ber_int_t err, - const char *matched, - const char *text, - BerVarray refs, - const char *rspoid, + SlapReply *rs, int state, - struct berval *cookie, - LDAPControl **ctrls ) + struct berval *cookie ) { char berbuf[LBER_ELEMENT_SIZEOF]; BerElement *ber = (BerElement *)berbuf; struct berval rspdata; - int ret, rc; + int ret; ber_init2( ber, NULL, LBER_USE_DER ); - if ( cookie == NULL ) + if ( cookie == NULL ) { ber_printf( ber, "{eN}", state ); - else + } else { ber_printf( ber, "{eON}", state, cookie ); + } ret = ber_flatten2( ber, &rspdata, 0 ); if ( ret < 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, RESULTS, - "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); + "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", + 0, 0, 0 ); #else - Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", + Debug( LDAP_DEBUG_TRACE, + "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, rc=LDAP_OTHER, - NULL, "internal error", NULL, NULL ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return ret; } - send_ldap_intermediate_resp( conn, op, err, matched, text, refs, rspoid, &rspdata, ctrls ); - + rs->sr_rspdata = &rspdata; + send_ldap_intermediate_resp( op, rs ); + rs->sr_rspdata = NULL; ber_free_buf( ber ); return LDAP_SUCCESS;