From 2668fd43f9799b91ffea74cfae0fc2eca45d19a4 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 29 Jun 2004 23:45:49 +0000 Subject: [PATCH] Sync with HEAD --- servers/slapd/add.c | 9 +- servers/slapd/back-bdb/add.c | 62 ++++-- servers/slapd/back-bdb/back-bdb.h | 9 +- servers/slapd/back-bdb/cache.c | 100 +++++---- servers/slapd/back-bdb/ctxcsn.c | 61 ++--- servers/slapd/back-bdb/delete.c | 60 ++++- servers/slapd/back-bdb/dn2entry.c | 12 +- servers/slapd/back-bdb/init.c | 2 + servers/slapd/back-bdb/modify.c | 135 +++++++++--- servers/slapd/back-bdb/modrdn.c | 158 ++++++++----- servers/slapd/back-bdb/proto-bdb.h | 10 +- servers/slapd/back-bdb/search.c | 77 ++++--- servers/slapd/bind.c | 11 +- servers/slapd/config.c | 334 +++++++++++++++++++--------- servers/slapd/connection.c | 98 +++++---- servers/slapd/controls.c | 10 + servers/slapd/daemon.c | 5 + servers/slapd/extended.c | 6 +- servers/slapd/filterentry.c | 19 +- servers/slapd/limits.c | 102 ++++++--- servers/slapd/oc.c | 3 +- servers/slapd/proto-slap.h | 1 + servers/slapd/result.c | 57 +++-- servers/slapd/schema_init.c | 343 +++++++++++++++++++++-------- servers/slapd/schema_prep.c | 27 +-- servers/slapd/search.c | 40 +++- servers/slapd/slap.h | 4 + servers/slapd/slapd.conf | 2 +- servers/slapd/slapi/slapi_utils.c | 2 +- servers/slapd/syncrepl.c | 180 +++++++++------ servers/slapd/value.c | 9 +- 31 files changed, 1316 insertions(+), 632 deletions(-) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index da0ae87789..db2b0743ba 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -82,7 +82,7 @@ do_add( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - return -1; + return SLAPD_DISCONNECT; } e = (Entry *) ch_calloc( 1, sizeof(Entry) ); @@ -125,12 +125,12 @@ do_add( Operation *op, SlapReply *rs ) if ( rtag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "do_add: conn %d decoding error \n", op->o_connid, 0, 0 ); + "do_add: conn %d decoding error \n", op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto done; } @@ -168,7 +168,7 @@ do_add( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto done; } @@ -383,7 +383,6 @@ do_add( Operation *op, SlapReply *rs ) #endif /* LDAP_SLAPI */ done: - slap_graduate_commit_csn( op ); if( modlist != NULL ) { diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 476043febe..104b289d7a 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -49,6 +49,7 @@ bdb_add(Operation *op, SlapReply *rs ) Entry *ctxcsn_e; int ctxcsn_added = 0; + LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; @@ -60,6 +61,8 @@ bdb_add(Operation *op, SlapReply *rs ) op->oq_add.rs_e->e_name.bv_val, 0, 0); #endif + ctrls[num_ctrls] = 0; + /* check entry's schema */ rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e, NULL, &rs->sr_text, textbuf, textlen ); @@ -344,23 +347,6 @@ retry: /* transaction retry */ goto return_results;; } - /* post-read */ - if( op->o_postread ) { - if ( slap_read_controls( op, rs, op->oq_add.rs_e, - &slap_post_read_bv, &ctrls[num_ctrls] ) ) - { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, DETAIL1, - "<=- bdb_add: post-read failed!\n", 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_TRACE, - "<=- bdb_add: post-read failed!\n", 0, 0, 0 ); -#endif - goto return_results; - } - ctrls[++num_ctrls] = NULL; - } - /* nested transaction */ rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags ); @@ -462,6 +448,26 @@ retry: /* transaction retry */ } } + /* post-read */ + if( op->o_postread ) { + if( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, op->oq_add.rs_e, + &slap_post_read_bv, postread_ctrl ) ) + { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "<=- bdb_add: post-read failed!\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "<=- bdb_add: post-read failed!\n", 0, 0, 0 ); +#endif + goto return_results; + } + } + if ( op->o_noop ) { if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; @@ -495,13 +501,23 @@ retry: /* transaction retry */ } if ( rs->sr_err == LDAP_SUCCESS && !op->o_no_psearch ) { - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); assert( BEI(e) ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, - LDAP_PSEARCH_BY_ADD ); + rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_ADD ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_add: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_add: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { @@ -555,5 +571,9 @@ done: op->o_private = NULL; } + if( postread_ctrl != NULL ) { + slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *postread_ctrl, &op->o_tmpmemctx ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 3420b0d9a1..e3846c9b9b 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -92,7 +92,13 @@ typedef struct bdb_entry_info { struct bdb_entry_info *bei_parent; ID bei_id; - int bei_state; + /* we use the bei_id as a lockobj, but we need to make the size != 4 + * to avoid conflicting with BDB's internal locks. So add a byte here + * that is always zero. + */ + char bei_lockpad; + + short bei_state; #define CACHE_ENTRY_DELETED 1 #define CACHE_ENTRY_NO_KIDS 2 #define CACHE_ENTRY_NOT_LINKED 4 @@ -129,6 +135,7 @@ typedef struct bdb_cache { EntryInfo *c_lrutail; /* lru - rem lru entries from here */ ldap_pvt_thread_rdwr_t c_rwlock; ldap_pvt_thread_mutex_t lru_mutex; + u_int32_t c_locker; /* used by lru cleaner */ } Cache; #define CACHE_READ_LOCK 0 diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 6002a9b83d..85d4d052d4 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -74,8 +74,8 @@ bdb_cache_entry_db_relock( if ( !lock ) return 0; - lockobj.data = ei; - lockobj.size = sizeof(ei->bei_parent) + sizeof(ei->bei_id); + lockobj.data = &ei->bei_id; + lockobj.size = sizeof(ei->bei_id) + 1; list[0].op = DB_LOCK_PUT; list[0].lock = *lock; @@ -121,8 +121,8 @@ bdb_cache_entry_db_lock( DB_ENV *env, u_int32_t locker, EntryInfo *ei, else db_rw = DB_LOCK_READ; - lockobj.data = ei; - lockobj.size = sizeof(ei->bei_parent) + sizeof(ei->bei_id); + lockobj.data = &ei->bei_id; + lockobj.size = sizeof(ei->bei_id) + 1; rc = LOCK_GET(env, locker, tryOnly ? DB_LOCK_NOWAIT : 0, &lockobj, db_rw, lock); @@ -532,7 +532,7 @@ bdb_cache_lru_add( /* If we can successfully writelock it, then * the object is idle. */ - if ( bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, elru, 1, 1, + if ( bdb_cache_entry_db_lock( bdb->bi_dbenv, bdb->bi_cache.c_locker, elru, 1, 1, lockp ) == 0 ) { /* If there's no entry, or this node is in * the process of linking into the cache, @@ -655,45 +655,53 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) { rc = DB_NOTFOUND; } else { - bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, *eip, 0, 0, lock ); - if ( !(*eip)->bei_e ) { - if (!ep) { - rc = bdb_id2entry( op->o_bd, tid, id, &ep ); - } - if ( rc == 0 ) { - bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, - *eip, 1, 0, lock ); - /* Make sure no other modifier beat us to it */ - if ( (*eip)->bei_e ) { - bdb_entry_return( ep ); - ep = NULL; - } else { - ep->e_private = *eip; + rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, *eip, 0, 0, lock ); + /* entry is protected now, we don't need to hold the entryinfo */ + if ( islocked ) { + bdb_cache_entryinfo_unlock( *eip ); + islocked = 0; + } + if ( rc == 0 ) { + if ( !(*eip)->bei_e ) { + if (!ep) { + rc = bdb_id2entry( op->o_bd, tid, id, &ep ); + } + if ( rc == 0 ) { + bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, + *eip, 1, 0, lock ); + /* Make sure no other modifier beat us to it */ + if ( (*eip)->bei_e ) { + bdb_entry_return( ep ); + ep = NULL; + } else { + ep->e_private = *eip; #ifdef BDB_HIER - bdb_fix_dn( ep, 0 ); + bdb_fix_dn( ep, 0 ); #endif - (*eip)->bei_e = ep; + (*eip)->bei_e = ep; + } + bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, + *eip, 0, 0, lock ); } - bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, - *eip, 0, 0, lock ); - } - } else { - /* If we had the entry already, this item - * is on the LRU list. - */ - lru_del = 1; + } else { + /* If we had the entry already, this item + * is on the LRU list. + */ + lru_del = 1; #ifdef BDB_HIER - rc = bdb_fix_dn( (*eip)->bei_e, 1 ); - if ( rc ) { - bdb_cache_entry_db_relock( bdb->bi_dbenv, - locker, *eip, 1, 0, lock ); - /* check again in case other modifier did it already */ - if ( bdb_fix_dn( (*eip)->bei_e, 1 ) ) - rc = bdb_fix_dn( (*eip)->bei_e, 2 ); - bdb_cache_entry_db_relock( bdb->bi_dbenv, - locker, *eip, 0, 0, lock ); - } + rc = bdb_fix_dn( (*eip)->bei_e, 1 ); + if ( rc ) { + bdb_cache_entry_db_relock( bdb->bi_dbenv, + locker, *eip, 1, 0, lock ); + /* check again in case other modifier did it already */ + if ( bdb_fix_dn( (*eip)->bei_e, 1 ) ) + rc = bdb_fix_dn( (*eip)->bei_e, 2 ); + bdb_cache_entry_db_relock( bdb->bi_dbenv, + locker, *eip, 0, 0, lock ); + } #endif + } + } } } @@ -749,11 +757,23 @@ bdb_cache_add( { EntryInfo *new, ei; struct berval rdn = e->e_name; + DB_LOCK lock; int rc; ei.bei_id = e->e_id; ei.bei_parent = eip; ei.bei_nrdn = *nrdn; + ei.bei_lockpad = 0; + + /* Lock this entry so that bdb_add can run to completion. + * It can only fail if BDB has run out of lock resources. + */ + rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, &ei, 1, 0, &lock ); + if ( rc ) { + bdb_cache_entryinfo_unlock( eip ); + return rc; + } + #ifdef BDB_HIER if ( nrdn->bv_len != e->e_nname.bv_len ) { char *ptr = strchr( rdn.bv_val, ',' ); @@ -1166,7 +1186,7 @@ bdb_cache_delete_entry( DB_LOCK *lock ) { ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock ); - if ( bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, ei, 1, 1, lock ) == 0 ) + if ( bdb_cache_entry_db_lock( bdb->bi_dbenv, bdb->bi_cache.c_locker, ei, 1, 1, lock ) == 0 ) { if ( ei->bei_e && !(ei->bei_state & CACHE_ENTRY_NOT_LINKED )) { LRU_DELETE( &bdb->bi_cache, ei ); diff --git a/servers/slapd/back-bdb/ctxcsn.c b/servers/slapd/back-bdb/ctxcsn.c index a76bae3331..294362430f 100644 --- a/servers/slapd/back-bdb/ctxcsn.c +++ b/servers/slapd/back-bdb/ctxcsn.c @@ -259,6 +259,7 @@ bdb_get_commit_csn( int rc; struct sync_cookie syncCookie = { NULL, -1, NULL}; syncinfo_t *si; + u_int32_t ctxcsn_locker = 0; if ( op->o_sync_mode != SLAP_SYNC_NONE && !LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) { @@ -282,21 +283,16 @@ consumer_ctxcsn_retry : } break; case LDAP_BUSY: - ch_free( ctxcsn_ndn.bv_val ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); - return LDAP_BUSY; + goto done; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto consumer_ctxcsn_retry; case DB_NOTFOUND: - ch_free( ctxcsn_ndn.bv_val ); - LOCK_ID_FREE( bdb->bi_dbenv, locker ); - return LDAP_OTHER; + rs->sr_err = LDAP_OTHER; + goto done; default: - ch_free( ctxcsn_ndn.bv_val ); - ctxcsn_ndn.bv_val = NULL; - LOCK_ID_FREE (bdb->bi_dbenv, locker ); - return LDAP_OTHER; + rs->sr_err = LDAP_OTHER; + goto done; } if ( ctxcsn_e ) { @@ -345,15 +341,12 @@ provider_ctxcsn_retry : 0, locker, ctxcsn_lock ); switch(rs->sr_err) { case 0: - ch_free( ctxcsn_ndn.bv_val ); if ( ctxcsn_ei ) { ctxcsn_e = ctxcsn_ei->bei_e; } break; case LDAP_BUSY: - ch_free( ctxcsn_ndn.bv_val ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); - return LDAP_BUSY; + goto done; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto provider_ctxcsn_retry; @@ -366,9 +359,10 @@ provider_ctxcsn_retry : if ( 0 ) { txn_retry: rs->sr_err = TXN_ABORT( ltid ); + ltid = NULL; if ( rs->sr_err != 0 ) { rs->sr_err = LDAP_OTHER; - return rs->sr_err; + goto done; } ldap_pvt_thread_yield(); bdb_trans_backoff( ++num_retries ); @@ -377,15 +371,17 @@ txn_retry: <id, bdb->bi_db_opflags ); if ( rs->sr_err != 0 ) { rs->sr_err = LDAP_OTHER; - return rs->sr_err; + goto done; } + ctxcsn_locker = TXN_ID ( ltid ); + rs->sr_err = bdb_csn_commit( op, rs, ltid, NULL, &suffix_ei, - &ctxcsn_e, &ctxcsn_added, locker ); + &ctxcsn_e, &ctxcsn_added, ctxcsn_locker ); switch( rs->sr_err ) { case BDB_CSN_ABORT: - LOCK_ID_FREE( bdb->bi_dbenv, locker ); - return LDAP_OTHER; + rs->sr_err = LDAP_OTHER; + goto done; case BDB_CSN_RETRY: goto txn_retry; } @@ -393,21 +389,22 @@ txn_retry: rs->sr_err = TXN_PREPARE( ltid, gid ); if ( rs->sr_err != 0 ) { rs->sr_err = LDAP_OTHER; - return rs->sr_err; + goto done; } bdb_cache_add( bdb, suffix_ei, ctxcsn_e, - (struct berval *)&slap_ldapsync_cn_bv, locker ); + (struct berval *)&slap_ldapsync_cn_bv, ctxcsn_locker ); rs->sr_err = TXN_COMMIT( ltid, 0 ); if ( rs->sr_err != 0 ) { rs->sr_err = LDAP_OTHER; - return rs->sr_err; + goto done; } rs->sr_err = bdb_dn2entry( op, NULL, &ctxcsn_ndn, &ctxcsn_ei, - 0, locker, ctxcsn_lock ); + 0, ctxcsn_locker, ctxcsn_lock ); ch_free( ctxcsn_ndn.bv_val ); + ctxcsn_ndn.bv_val = NULL; if ( ctxcsn_ei ) { ctxcsn_e = ctxcsn_ei->bei_e; @@ -415,9 +412,8 @@ txn_retry: break; default: - ch_free( ctxcsn_ndn.bv_val ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); - return LDAP_OTHER; + rs->sr_err = LDAP_OTHER; + goto done; } if ( ctxcsn_e ) { @@ -433,5 +429,16 @@ txn_retry: } } - return LDAP_SUCCESS; + ltid = NULL; + rs->sr_err = LDAP_SUCCESS; + +done: + if( ltid != NULL ) { + TXN_ABORT( ltid ); + } + + if ( ctxcsn_ndn.bv_val != NULL ) + ch_free( ctxcsn_ndn.bv_val ); + + return rs->sr_err; } diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index cdd614bb4c..148230ec01 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -48,14 +48,18 @@ bdb_delete( Operation *op, SlapReply *rs ) Entry *ctxcsn_e; int ctxcsn_added = 0; + LDAPControl **preread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; int parent_is_glue = 0; int parent_is_leaf = 0; + ctrls[num_ctrls] = 0; + #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ARGS, "==> bdb_delete: %s\n", op->o_req_dn.bv_val, 0, 0 ); + LDAP_LOG ( OPERATION, ARGS, "==> bdb_delete: %s\n", + op->o_req_dn.bv_val, 0, 0 ); #else Debug( LDAP_DEBUG_ARGS, "==> bdb_delete: %s\n", op->o_req_dn.bv_val, 0, 0 ); @@ -67,6 +71,10 @@ retry: /* transaction retry */ bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e); e = NULL; } + if( p != NULL ) { + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); + p = NULL; + } #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "==> bdb_delete: retrying...\n", 0, 0, 0 ); @@ -197,7 +205,19 @@ retry: /* transaction retry */ goto done; } - bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, locker, &plock ); + rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, locker, &plock ); + switch( rc ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + case 0: + case DB_NOTFOUND: + break; + default: + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + goto return_results; + } if ( eip ) p = eip->bei_e; if ( pdn.bv_len != 0 ) { @@ -219,9 +239,6 @@ retry: /* transaction retry */ rs->sr_err = access_allowed( op, p, children, NULL, ACL_WRITE, NULL ); - bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); - p = NULL; - if ( !rs->sr_err ) { switch( opinfo.boi_err ) { case DB_LOCK_DEADLOCK: @@ -346,8 +363,12 @@ retry: /* transaction retry */ /* pre-read */ if( op->o_preread ) { + if( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } if( slap_read_controls( op, rs, e, - &slap_pre_read_bv, &ctrls[num_ctrls] ) ) + &slap_pre_read_bv, preread_ctrl ) ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, @@ -358,7 +379,6 @@ retry: /* transaction retry */ #endif goto return_results; } - ctrls[++num_ctrls] = NULL; } /* nested transaction */ @@ -480,8 +500,6 @@ retry: /* transaction retry */ goto return_results; } - bdb_cache_find_id( op, lt2, eip->bei_id, &eip, 0, locker, &plock ); - if ( eip ) p = eip->bei_e; if ( pdn.bv_len != 0 ) { parent_is_glue = is_entry_glue(p); rs->sr_err = bdb_cache_children( op, lt2, p ); @@ -561,11 +579,22 @@ retry: /* transaction retry */ } if ( rs->sr_err == LDAP_SUCCESS && !op->o_no_psearch ) { - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_DELETE ); + rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_DELETE ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_delete: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_delete: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } rs->sr_err = TXN_COMMIT( ltid, 0 ); @@ -620,6 +649,9 @@ return_results: } done: + if ( p ) + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); + /* free entry */ if( e != NULL ) { if ( rs->sr_err == LDAP_SUCCESS ) { @@ -635,5 +667,9 @@ done: op->o_private = NULL; } + if( preread_ctrl != NULL ) { + slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *preread_ctrl, &op->o_tmpmemctx ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/dn2entry.c b/servers/slapd/back-bdb/dn2entry.c index 25d79e5256..c221edaa08 100644 --- a/servers/slapd/back-bdb/dn2entry.c +++ b/servers/slapd/back-bdb/dn2entry.c @@ -38,7 +38,7 @@ bdb_dn2entry( DB_LOCK *lock ) { EntryInfo *ei = NULL; - int rc; + int rc, rc2; #ifdef NEW_LOGGING LDAP_LOG ( CACHE, ARGS, "bdb_dn2entry(\"%s\")\n", dn->bv_val, 0, 0 ); @@ -56,10 +56,11 @@ bdb_dn2entry( * or not. */ *e = ei; - if ( ei && ei->bei_id ) - bdb_cache_find_id( op, tid, ei->bei_id, + if ( ei && ei->bei_id ) { + rc2 = bdb_cache_find_id( op, tid, ei->bei_id, &ei, 1, locker, lock ); - else if ( ei ) + if ( rc2 ) rc = rc2; + } else if ( ei ) bdb_cache_entryinfo_unlock( ei ); } else if ( ei ) { bdb_cache_entryinfo_unlock( ei ); @@ -72,8 +73,9 @@ bdb_dn2entry( } else if ( matched && rc == DB_NOTFOUND ) { /* always return EntryInfo */ ei = ei->bei_parent; - bdb_cache_find_id( op, tid, ei->bei_id, &ei, 1, + rc2 = bdb_cache_find_id( op, tid, ei->bei_id, &ei, 1, locker, lock ); + if ( rc2 ) rc = rc2; *e = ei; } } diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 3bc535b211..9742b9ca24 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -447,6 +447,8 @@ bdb_db_open( BackendDB *be ) return rc; } + bdb->bi_dbenv->lock_id(bdb->bi_dbenv, &bdb->bi_cache.c_locker); + /* open (and create) index databases */ return 0; } diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index c8d65d789f..ce0195e35d 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -116,8 +116,11 @@ int bdb_modify_internal( break; case LDAP_MOD_DELETE: - if ( glue_attr_delete ) + if ( glue_attr_delete ) { + err = LDAP_SUCCESS; break; + } + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify_internal: delete\n", 0, 0, 0 ); @@ -353,6 +356,8 @@ bdb_modify( Operation *op, SlapReply *rs ) int num_retries = 0; + LDAPControl **preread_ctrl = NULL; + LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; @@ -364,11 +369,15 @@ bdb_modify( Operation *op, SlapReply *rs ) int ctxcsn_added = 0; #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "bdb_modify: %s\n", op->o_req_dn.bv_val, 0, 0 ); + LDAP_LOG ( OPERATION, ENTRY, "bdb_modify: %s\n", + op->o_req_dn.bv_val, 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, "bdb_modify: %s\n", op->o_req_dn.bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, "bdb_modify: %s\n", + op->o_req_dn.bv_val, 0, 0 ); #endif + ctrls[num_ctrls] = NULL; + if( 0 ) { retry: /* transaction retry */ if( e != NULL ) { @@ -462,7 +471,9 @@ retry: /* transaction retry */ e = ei->bei_e; /* acquire and lock entry */ /* FIXME: dn2entry() should return non-glue entry */ - if (( rs->sr_err == DB_NOTFOUND ) || ( !manageDSAit && e && is_entry_glue( e ))) { + if (( rs->sr_err == DB_NOTFOUND ) || + ( !manageDSAit && e && is_entry_glue( e ))) + { if ( e != NULL ) { rs->sr_matched = ch_strdup( e->e_dn ); rs->sr_ref = is_entry_referral( e ) @@ -505,7 +516,9 @@ retry: /* transaction retry */ rs->sr_ref = get_entry_referrals( op, e ); #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify: entry is referral\n", 0, 0, 0 ); + LDAP_LOG ( OPERATION, DETAIL1, + "bdb_modify: entry is referral\n", + 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "bdb_modify: entry is referral\n", @@ -530,16 +543,31 @@ retry: /* transaction retry */ } if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop && !op->o_no_psearch ) { - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch(op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); + rc = bdb_psearch(op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } if( op->o_preread ) { + if( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } if ( slap_read_controls( op, rs, e, - &slap_pre_read_bv, &ctrls[num_ctrls] ) ) + &slap_pre_read_bv, preread_ctrl ) ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, @@ -550,8 +578,6 @@ retry: /* transaction retry */ #endif goto return_results; } - ctrls[++num_ctrls] = NULL; - op->o_preread = 0; /* prevent redo on retry */ } /* nested transaction */ @@ -561,7 +587,8 @@ retry: /* transaction retry */ if( rs->sr_err != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, - "bdb_modify: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 ); + "bdb_modify: txn_begin(2) failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); #else Debug( LDAP_DEBUG_TRACE, "bdb_modify: txn_begin(2) failed: %s (%d)\n", @@ -591,29 +618,13 @@ retry: /* transaction retry */ switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: + attrs_free( dummy.e_attrs ); + dummy.e_attrs = NULL; goto retry; } goto return_results; } - if( op->o_postread ) { - if( slap_read_controls( op, rs, e, - &slap_post_read_bv, &ctrls[num_ctrls] ) ) - { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, DETAIL1, - "<=- bdb_modify: post-read failed!\n", 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_TRACE, - "<=- bdb_modify: post-read failed!\n", 0, 0, 0 ); -#endif - goto return_results; - } - ctrls[++num_ctrls] = NULL; - op->o_postread = 0; /* prevent redo on retry */ - /* FIXME: should read entry on the last retry */ - } - /* change the entry itself */ rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy ); if ( rs->sr_err != 0 ) { @@ -628,6 +639,8 @@ retry: /* transaction retry */ switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: + attrs_free( dummy.e_attrs ); + dummy.e_attrs = NULL; goto retry; } rs->sr_text = "entry update failed"; @@ -647,10 +660,31 @@ retry: /* transaction retry */ case BDB_CSN_ABORT : goto return_results; case BDB_CSN_RETRY : + attrs_free( dummy.e_attrs ); + dummy.e_attrs = NULL; goto retry; } } + if( op->o_postread ) { + if( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if( slap_read_controls( op, rs, e, + &slap_post_read_bv, postread_ctrl ) ) + { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "<=- bdb_modify: post-read failed!\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "<=- bdb_modify: post-read failed!\n", 0, 0, 0 ); +#endif + goto return_results; + } + } + if( op->o_noop ) { if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; @@ -663,6 +697,8 @@ retry: /* transaction retry */ switch( rc ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: + attrs_free( dummy.e_attrs ); + dummy.e_attrs = NULL; goto retry; } @@ -675,20 +711,42 @@ retry: /* transaction retry */ if ( rs->sr_err == LDAP_SUCCESS ) { /* Loop through in-scope entries for each psearch spec */ - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); pm_list = LDAP_LIST_FIRST(&op->o_pm_list); while ( pm_list != NULL ) { - bdb_psearch(op, rs, pm_list->ps_op, + rc = bdb_psearch(op, rs, pm_list->ps_op, e, LDAP_PSEARCH_BY_SCOPEOUT); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modify: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } LDAP_LIST_REMOVE ( pm_list, ps_link ); pm_prev = pm_list; pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); ch_free( pm_prev ); } + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } rs->sr_err = TXN_COMMIT( ltid, 0 ); @@ -754,5 +812,14 @@ done: if( e != NULL ) { bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e); } + + if( preread_ctrl != NULL ) { + slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *preread_ctrl, &op->o_tmpmemctx ); + } + if( postread_ctrl != NULL ) { + slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *postread_ctrl, &op->o_tmpmemctx ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index 749f6571de..8d29504e7c 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -60,6 +60,8 @@ bdb_modrdn( Operation *op, SlapReply *rs ) int num_retries = 0; + LDAPControl **preread_ctrl = NULL; + LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; @@ -73,6 +75,8 @@ bdb_modrdn( Operation *op, SlapReply *rs ) int parent_is_glue = 0; int parent_is_leaf = 0; + ctrls[num_ctrls] = NULL; + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n", op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, @@ -789,8 +793,12 @@ retry: /* transaction retry */ } if( op->o_preread ) { + if( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } if( slap_read_controls( op, rs, e, - &slap_pre_read_bv, &ctrls[num_ctrls] ) ) + &slap_pre_read_bv, preread_ctrl ) ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, @@ -801,8 +809,6 @@ retry: /* transaction retry */ #endif goto return_results; } - ctrls[++num_ctrls] = NULL; - op->o_preread = 0; /* prevent redo on retry */ } /* nested transaction */ @@ -888,11 +894,22 @@ retry: /* transaction retry */ } if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop && !op->o_no_psearch ) { - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); + rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } /* modify entry */ @@ -919,24 +936,6 @@ retry: /* transaction retry */ goto return_results; } - if( op->o_postread ) { - if( slap_read_controls( op, rs, e, - &slap_post_read_bv, &ctrls[num_ctrls] ) ) - { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, DETAIL1, - "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_TRACE, - "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 ); -#endif - goto return_results; - } - ctrls[++num_ctrls] = NULL; - op->o_postread = 0; /* prevent redo on retry */ - /* FIXME: should read entry on the last retry */ - } - /* id2entry index */ rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e ); if ( rs->sr_err != 0 ) { @@ -959,37 +958,35 @@ retry: /* transaction retry */ goto return_results; } - bdb_cache_find_id( op, lt2, eip->bei_id, &eip, 0, locker, &plock ); - if ( eip ) p = eip->bei_e; - if ( p_ndn.bv_len != 0 ) { - parent_is_glue = is_entry_glue(p); - rs->sr_err = bdb_cache_children( op, lt2, p ); - if ( rs->sr_err != DB_NOTFOUND ) { - switch( rs->sr_err ) { - case DB_LOCK_DEADLOCK: - case DB_LOCK_NOTGRANTED: - goto retry; - case 0: - break; - default: + if ( p_ndn.bv_len != 0 ) { + parent_is_glue = is_entry_glue(p); + rs->sr_err = bdb_cache_children( op, lt2, p ); + if ( rs->sr_err != DB_NOTFOUND ) { + switch( rs->sr_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + case 0: + break; + default: #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, - "<=- bdb_modrdn: has_children failed %s (%d)\n", - db_strerror(rs->sr_err), rs->sr_err, 0 ); + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: has_children failed %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); #else - Debug(LDAP_DEBUG_ARGS, - "<=- bdb_modrdn: has_children failed: %s (%d)\n", - db_strerror(rs->sr_err), rs->sr_err, 0 ); + Debug(LDAP_DEBUG_ARGS, + "<=- bdb_modrdn: has_children failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); #endif - rs->sr_err = LDAP_OTHER; - rs->sr_text = "internal error"; - goto return_results; - } - parent_is_leaf = 1; - } - bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); - p = NULL; - } + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + goto return_results; + } + parent_is_leaf = 1; + } + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); + p = NULL; + } if ( TXN_COMMIT( lt2, 0 ) != 0 ) { rs->sr_err = LDAP_OTHER; @@ -1008,6 +1005,25 @@ retry: /* transaction retry */ } } + if( op->o_postread ) { + if( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if( slap_read_controls( op, rs, e, + &slap_post_read_bv, postread_ctrl ) ) + { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 ); +#endif + goto return_results; + } + } + if( op->o_noop ) { if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; @@ -1034,20 +1050,42 @@ retry: /* transaction retry */ if ( rs->sr_err == LDAP_SUCCESS ) { /* Loop through in-scope entries for each psearch spec */ - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); pm_list = LDAP_LIST_FIRST(&op->o_pm_list); while ( pm_list != NULL ) { - bdb_psearch(op, rs, pm_list->ps_op, + rc = bdb_psearch(op, rs, pm_list->ps_op, e, LDAP_PSEARCH_BY_SCOPEOUT); + if ( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modrdn: persistent search failed (%d,%d)\n", + rc, rs->sr_err, 0 ); +#endif + } pm_prev = pm_list; LDAP_LIST_REMOVE ( pm_list, ps_link ); pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); ch_free( pm_prev ); } + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); } if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { @@ -1154,5 +1192,13 @@ done: op->o_private = NULL; } + if( preread_ctrl != NULL ) { + slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *preread_ctrl, &op->o_tmpmemctx ); + } + if( postread_ctrl != NULL ) { + slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + slap_sl_free( *postread_ctrl, &op->o_tmpmemctx ); + } return rs->sr_err; } diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 8561e1ca5d..40a9f5a867 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -537,10 +537,19 @@ int bdb_locker_id( Operation *op, DB_ENV *env, int *locker ); #define bdb_abandon BDB_SYMBOL(abandon) #define bdb_cancel BDB_SYMBOL(cancel) #define bdb_do_search BDB_SYMBOL(do_search) +#define bdb_psearch BDB_SYMBOL(psearch) BI_op_abandon bdb_abandon; BI_op_cancel bdb_cancel; +int bdb_psearch( + Operation *op, + SlapReply *rs, + Operation *ps_op, + Entry *entry, + int psearch_type +); + int bdb_do_search( Operation *op, SlapReply *rs, @@ -548,7 +557,6 @@ int bdb_do_search( Entry *entry, int psearch_type ); -#define bdb_psearch(op, rs, sop, e, ps_type) bdb_do_search(op, rs, sop, e, ps_type) /* * trans.c diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 552f30a108..31a8776796 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -361,6 +361,18 @@ int bdb_search( Operation *op, SlapReply *rs ) return bdb_do_search( op, rs, op, NULL, 0 ); } +int bdb_psearch( Operation *op, SlapReply *rs, Operation *sop, + Entry *ps_e, int ps_type ) +{ + int rc; + + sop->o_private = op->o_private; + rc = bdb_do_search( op, rs, sop, ps_e, ps_type ); + sop->o_private = NULL; + + return rc; +} + /* For persistent searches, op is the currently executing operation, * sop is the persistent search. For regular searches, sop = op. */ @@ -408,14 +420,18 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop, BerVarray syncUUID_set = NULL; int syncUUID_set_cnt = 0; + struct bdb_op_info *opinfo = NULL; + DB_TXN *ltid = NULL; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "bdb_search\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_TRACE, "=> bdb_search\n", - 0, 0, 0); + Debug( LDAP_DEBUG_TRACE, "=> bdb_search\n", 0, 0, 0); #endif attrs = sop->oq_search.rs_attrs; + opinfo = (struct bdb_op_info *) op->o_private; + if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) { struct slap_session_entry *sent; if ( sop->o_sync_state.sid >= 0 ) { @@ -509,14 +525,19 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop, } } - rs->sr_err = LOCK_ID( bdb->bi_dbenv, &locker ); + if ( opinfo ) { + ltid = opinfo->boi_txn; + locker = TXN_ID( ltid ); + } else { + rs->sr_err = LOCK_ID( bdb->bi_dbenv, &locker ); - switch(rs->sr_err) { - case 0: - break; - default: - send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); - return rs->sr_err; + switch(rs->sr_err) { + case 0: + break; + default: + send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); + return rs->sr_err; + } } if ( sop->o_req_ndn.bv_len == 0 ) { @@ -532,7 +553,7 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop, } else { dn2entry_retry: /* get entry with reader lock */ - rs->sr_err = bdb_dn2entry( op, NULL, &sop->o_req_ndn, &ei, + rs->sr_err = bdb_dn2entry( op, ltid, &sop->o_req_ndn, &ei, 1, locker, &lock ); } @@ -545,14 +566,16 @@ dn2entry_retry: break; case LDAP_BUSY: send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + if ( !opinfo ) + LOCK_ID_FREE (bdb->bi_dbenv, locker ); return LDAP_BUSY; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; default: send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + if ( !opinfo ) + LOCK_ID_FREE (bdb->bi_dbenv, locker ); return rs->sr_err; } @@ -592,7 +615,8 @@ dn2entry_retry: rs->sr_matched = matched_dn.bv_val; send_ldap_result( sop, rs ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + if ( !opinfo ) + LOCK_ID_FREE (bdb->bi_dbenv, locker ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; @@ -634,7 +658,8 @@ dn2entry_retry: rs->sr_matched = matched_dn.bv_val; send_ldap_result( sop, rs ); - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + if ( !opinfo ) + LOCK_ID_FREE (bdb->bi_dbenv, locker ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; ber_memfree( matched_dn.bv_val ); @@ -895,7 +920,7 @@ loop_begin: id2entry_retry: /* get the entry with reader lock */ ei = NULL; - rs->sr_err = bdb_cache_find_id( op, NULL, + rs->sr_err = bdb_cache_find_id( op, ltid, id, &ei, 0, locker, &lock ); if (rs->sr_err == LDAP_BUSY) { @@ -1468,7 +1493,8 @@ done: bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); } - LOCK_ID_FREE( bdb->bi_dbenv, locker ); + if ( !opinfo ) + LOCK_ID_FREE( bdb->bi_dbenv, locker ); ber_bvfree( search_context_csn ); @@ -1709,17 +1735,17 @@ send_paged_response( LDAPControl ctrl, *ctrls[2]; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; - struct berval cookie = BER_BVC( "" ); PagedResultsCookie respcookie; + struct berval cookie; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, - "send_paged_response: lastid: (0x%08lx) " - "nentries: (0x%081x)\n", + "send_paged_response: lastid=0x%08lx nentries=%d\n", lastid ? *lastid : 0, rs->sr_nentries, NULL ); #else - Debug(LDAP_DEBUG_ARGS, "send_paged_response: lastid: (0x%08lx) " - "nentries: (0x%081x)\n", lastid ? *lastid : 0, rs->sr_nentries, NULL ); + Debug(LDAP_DEBUG_ARGS, + "send_paged_response: lastid=0x%08lx nentries=%d\n", + lastid ? *lastid : 0, rs->sr_nentries, NULL ); #endif ctrl.ldctl_value.bv_val = NULL; @@ -1735,17 +1761,16 @@ send_paged_response( } else { respcookie = ( PagedResultsCookie )0; + cookie.bv_val = ""; + cookie.bv_len = 0; } op->o_conn->c_pagedresults_state.ps_cookie = respcookie; op->o_conn->c_pagedresults_state.ps_count = op->o_pagedresults_state.ps_count + rs->sr_nentries; - /* - * FIXME: we should consider sending an estimate of the entries - * left, after appropriate security check is done - */ - ber_printf( ber, "{iO}", tentries, &cookie ); + /* return size of 0 -- no estimate */ + ber_printf( ber, "{iO}", 0, &cookie ); if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) { goto done; diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index 1423aca172..6a66985587 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -41,8 +41,7 @@ int do_bind( Operation *op, - SlapReply *rs -) + SlapReply *rs ) { BerElement *ber = op->o_ber; ber_int_t version; @@ -117,7 +116,7 @@ do_bind( Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } @@ -308,11 +307,9 @@ do_bind( ber_dupbv( &op->o_conn->c_ndn, &op->o_conn->c_dn ); } op->o_tmpfree( op->orb_edn.bv_val, op->o_tmpmemctx ); - op->orb_edn.bv_val = NULL; - op->orb_edn.bv_len = 0; + BER_BVZERO( &op->orb_edn ); op->o_conn->c_authmech = op->o_conn->c_sasl_bind_mech; - op->o_conn->c_sasl_bind_mech.bv_val = NULL; - op->o_conn->c_sasl_bind_mech.bv_len = 0; + BER_BVZERO( &op->o_conn->c_sasl_bind_mech ); op->o_conn->c_sasl_bind_in_progress = 0; op->o_conn->c_sasl_ssf = op->orb_ssf; diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 9fa278a724..afcfdcf1f7 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -120,6 +120,8 @@ read_config( const char *fname, int depth ) LDAPURLDesc *ludp; static BackendInfo *bi = NULL; static BackendDB *be = NULL; + char *next; + vals[1].bv_val = NULL; @@ -259,7 +261,7 @@ read_config( const char *fname, int depth ) if ( cargc < 2 ) { #ifdef NEW_LOGGING LDAP_LOG( CONFIG, CRIT, - "%s: line %d: missing level in \"concurrency \" " " line\n", fname, lineno, 0 ); #else Debug( LDAP_DEBUG_ANY, @@ -270,7 +272,19 @@ read_config( const char *fname, int depth ) return( 1 ); } - c = atoi( cargv[1] ); + c = strtol( cargv[1], &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: unable to parse level \"%s\" in \"concurrency \" " + " line\n", fname, lineno, cargv[1] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse level \"%s\" in \"concurrency \" line\n", + fname, lineno, cargv[1] ); +#endif + return( 1 ); + } if( c < 1 ) { #ifdef NEW_LOGGING @@ -541,7 +555,19 @@ read_config( const char *fname, int depth ) return( 1 ); } - c = atoi( cargv[1] ); + c = strtol( cargv[1], &next, 10 ); + if (next == NULL || next[0] != '\0' ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: unable to parse count \"%s\" in \"threads \" line\n", + fname, lineno, cargv[1] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse count \"%s\" in \"threads \" line\n", + fname, lineno, cargv[1] ); +#endif + return( 1 ); + } if( c < 0 ) { #ifdef NEW_LOGGING @@ -815,8 +841,6 @@ read_config( const char *fname, int depth ) if ( strcasecmp( cargv[i], "unlimited" ) == 0 ) { lim->lms_s_soft = -1; } else { - char *next; - lim->lms_s_soft = strtol( cargv[i] , &next, 0 ); if ( next == cargv[i] ) { #ifdef NEW_LOGGING @@ -895,8 +919,6 @@ read_config( const char *fname, int depth ) if ( strcasecmp( cargv[i], "unlimited" ) == 0 ) { lim->lms_t_soft = -1; } else { - char *next; - lim->lms_t_soft = strtol( cargv[i] , &next, 0 ); if ( next == cargv[i] ) { #ifdef NEW_LOGGING @@ -1131,25 +1153,38 @@ read_config( const char *fname, int depth ) "%s: line %d: depth line must appear inside a database definition.\n", fname, lineno, 0 ); #endif - return 1; + return 1; + } + + i = strtol( cargv[1], &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, INFO, + "%s: line %d: unable to parse depth \"%s\" in \"maxDerefDepth \" " + "line.\n", fname, lineno, cargv[1] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse depth \"%s\" in \"maxDerefDepth \" " + "line.\n", fname, lineno, cargv[1] ); +#endif + return 1; + } - } else if ((i = atoi(cargv[1])) < 0) { + if (i < 0) { #ifdef NEW_LOGGING LDAP_LOG( CONFIG, INFO, "%s: line %d: depth must be positive.\n", - fname, lineno ,0 ); + fname, lineno, 0 ); #else Debug( LDAP_DEBUG_ANY, "%s: line %d: depth must be positive.\n", fname, lineno, 0 ); #endif - return 1; - + return 1; - } else { - be->be_max_deref_depth = i; - } + } + be->be_max_deref_depth = i; /* set magic "root" dn for this database */ } else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) { @@ -1504,64 +1539,67 @@ read_config( const char *fname, int depth ) } for( i=1; i < cargc; i++ ) { - if( strncasecmp( cargv[i], "ssf=", - sizeof("ssf") ) == 0 ) + slap_ssf_t *tgt; + char *src; + + if ( strncasecmp( cargv[i], "ssf=", + STRLENOF("ssf=") ) == 0 ) { - set->sss_ssf = - atoi( &cargv[i][sizeof("ssf")] ); + tgt = &set->sss_ssf; + src = &cargv[i][STRLENOF("ssf=")]; - } else if( strncasecmp( cargv[i], "transport=", - sizeof("transport") ) == 0 ) + } else if ( strncasecmp( cargv[i], "transport=", + STRLENOF("transport=") ) == 0 ) { - set->sss_transport = - atoi( &cargv[i][sizeof("transport")] ); + tgt = &set->sss_transport; + src = &cargv[i][STRLENOF("transport=")]; - } else if( strncasecmp( cargv[i], "tls=", - sizeof("tls") ) == 0 ) + } else if ( strncasecmp( cargv[i], "tls=", + STRLENOF("tls=") ) == 0 ) { - set->sss_tls = - atoi( &cargv[i][sizeof("tls")] ); + tgt = &set->sss_tls; + src = &cargv[i][STRLENOF("tls=")]; - } else if( strncasecmp( cargv[i], "sasl=", - sizeof("sasl") ) == 0 ) + } else if ( strncasecmp( cargv[i], "sasl=", + STRLENOF("sasl=") ) == 0 ) { - set->sss_sasl = - atoi( &cargv[i][sizeof("sasl")] ); + tgt = &set->sss_sasl; + src = &cargv[i][STRLENOF("sasl=")]; - } else if( strncasecmp( cargv[i], "update_ssf=", - sizeof("update_ssf") ) == 0 ) + } else if ( strncasecmp( cargv[i], "update_ssf=", + STRLENOF("update_ssf=") ) == 0 ) { - set->sss_update_ssf = - atoi( &cargv[i][sizeof("update_ssf")] ); + tgt = &set->sss_update_ssf; + src = &cargv[i][STRLENOF("update_ssf=")]; - } else if( strncasecmp( cargv[i], "update_transport=", - sizeof("update_transport") ) == 0 ) + } else if ( strncasecmp( cargv[i], "update_transport=", + STRLENOF("update_transport=") ) == 0 ) { - set->sss_update_transport = - atoi( &cargv[i][sizeof("update_transport")] ); + tgt = &set->sss_update_transport; + src = &cargv[i][STRLENOF("update_transport=")]; - } else if( strncasecmp( cargv[i], "update_tls=", - sizeof("update_tls") ) == 0 ) + } else if ( strncasecmp( cargv[i], "update_tls=", + STRLENOF("update_tls=") ) == 0 ) { - set->sss_update_tls = - atoi( &cargv[i][sizeof("update_tls")] ); + tgt = &set->sss_update_tls; + src = &cargv[i][STRLENOF("update_tls=")]; - } else if( strncasecmp( cargv[i], "update_sasl=", - sizeof("update_sasl") ) == 0 ) + } else if ( strncasecmp( cargv[i], "update_sasl=", + STRLENOF("update_sasl=") ) == 0 ) { - set->sss_update_sasl = - atoi( &cargv[i][sizeof("update_sasl")] ); + tgt = &set->sss_update_sasl; + src = &cargv[i][STRLENOF("update_sasl=")]; - } else if( strncasecmp( cargv[i], "simple_bind=", - sizeof("simple_bind") ) == 0 ) + } else if ( strncasecmp( cargv[i], "simple_bind=", + STRLENOF("simple_bind=") ) == 0 ) { - set->sss_simple_bind = - atoi( &cargv[i][sizeof("simple_bind")] ); + tgt = &set->sss_simple_bind; + src = &cargv[i][STRLENOF("simple_bind=")]; } else { #ifdef NEW_LOGGING LDAP_LOG( CONFIG, CRIT, - "%s: line %d: unknown factor %S in " + "%s: line %d: unknown factor %s in " "\"security \" line.\n", fname, lineno, cargv[1] ); #else @@ -1572,7 +1610,24 @@ read_config( const char *fname, int depth ) return( 1 ); } + + *tgt = strtol( src, &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: unable to parse factor \"%s\" in " + "\"security \" line.\n", + fname, lineno, cargv[1] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse factor \"%s\" in \"security \" line\n", + fname, lineno, cargv[i] ); +#endif + + return( 1 ); + } } + /* where to send clients when we don't hold it */ } else if ( strcasecmp( cargv[0], "referral" ) == 0 ) { if ( cargc < 2 ) { @@ -1640,10 +1695,22 @@ read_config( const char *fname, int depth ) "%s: line %d: Error in debug directive, \"debug subsys level\"\n", fname, lineno, 0 ); #endif - return( 1 ); } - level = atoi( cargv[2] ); + level = strtol( cargv[2], &next, 10 ); + if ( next == NULL || next[0] != '\0' ){ +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: unable to parse level \"%s\" in debug directive, " + "\"debug \"\n", fname, lineno , cargv[2] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse level \"%s\" in debug directive, " + "\"debug \"\n", fname, lineno , cargv[2] ); +#endif + return( 1 ); + } + if ( level <= 0 ) level = lutil_mnem2level( cargv[2] ); lutil_set_debug_level( cargv[1], level ); /* specify an Object Identifier macro */ @@ -1770,11 +1837,11 @@ read_config( const char *fname, int depth ) if ( cargc < 2 ) { #ifdef NEW_LOGGING LDAP_LOG( CONFIG, CRIT, - "%s: line %d: missing level in \"loglevel \"" + "%s: line %d: missing level(s) in \"loglevel [...]\"" " line.\n", fname, lineno , 0 ); #else Debug( LDAP_DEBUG_ANY, - "%s: line %d: missing level in \"loglevel \" line\n", + "%s: line %d: missing level(s) in \"loglevel [...]\" line\n", fname, lineno, 0 ); #endif @@ -1784,7 +1851,21 @@ read_config( const char *fname, int depth ) ldap_syslog = 0; for( i=1; i < cargc; i++ ) { - ldap_syslog += atoi( cargv[1] ); + int level = strtol( cargv[i], &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: unable to parse level \"%s\" in \"loglevel [...]\"" + " line.\n", fname, lineno , cargv[i] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unable to parse level \"%s\" in \"loglevel [...]\"" + " line.\n", fname, lineno , cargv[i] ); +#endif + return( 1 ); + } + + ldap_syslog |= level; } /* list of sync replication information in this backend (slave only) */ @@ -2886,12 +2967,15 @@ add_syncrepl( si->si_attrs[0] = NULL; si->si_type = LDAP_SYNC_REFRESH_ONLY; si->si_interval = 86400; + si->si_retryinterval = 0; + si->si_retrynum_init = 0; + si->si_retrynum = 0; si->si_syncCookie.ctxcsn = NULL; si->si_syncCookie.octet_str = NULL; si->si_syncCookie.sid = -1; si->si_manageDSAit = 0; - si->si_tlimit = -1; - si->si_slimit = -1; + si->si_tlimit = 0; + si->si_slimit = 0; si->si_syncUUID_ndn.bv_val = NULL; si->si_syncUUID_ndn.bv_len = 0; @@ -3002,6 +3086,8 @@ add_syncrepl( #define SLIMITSTR "sizelimit" #define TLIMITSTR "timelimit" +#define RETRYSTR "retry" + #define GOT_ID 0x0001 #define GOT_PROVIDER 0x0002 #define GOT_METHOD 0x0004 @@ -3190,54 +3276,104 @@ parse_syncrepl_line( } else if ( !strncasecmp( cargv[ i ], INTERVALSTR, sizeof( INTERVALSTR ) - 1 ) ) { - char *hstr; - char *mstr; - char *dstr; - char *sstr; - int dd, hh, mm, ss; val = cargv[ i ] + sizeof( INTERVALSTR ); - dstr = val; - hstr = strchr( dstr, ':' ); - if ( hstr == NULL ) { - fprintf( stderr, "Error: parse_syncrepl_line: " - "invalid interval \"%s\"\n", val ); - return 1; - } - *hstr++ = '\0'; - mstr = strchr( hstr, ':' ); - if ( mstr == NULL ) { - fprintf( stderr, "Error: parse_syncrepl_line: " - "invalid interval \"%s\"\n", val ); - return 1; - } - *mstr++ = '\0'; - sstr = strchr( mstr, ':' ); - if ( sstr == NULL ) { - fprintf( stderr, "Error: parse_syncrepl_line: " - "invalid interval \"%s\"\n", val ); - return 1; - } - *sstr++ = '\0'; - - dd = atoi( dstr ); - hh = atoi( hstr ); - mm = atoi( mstr ); - ss = atoi( sstr ); - if (( hh > 24 ) || ( hh < 0 ) || - ( mm > 60 ) || ( mm < 0 ) || - ( ss > 60 ) || ( ss < 0 ) || ( dd < 0 )) { - fprintf( stderr, "Error: parse_syncrepl_line: " - "invalid interval \"%s\"\n", val ); - return 1; + if ( si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ) { + si->si_interval = 0; + } else { + char *hstr; + char *mstr; + char *dstr; + char *sstr; + int dd, hh, mm, ss; + dstr = val; + hstr = strchr( dstr, ':' ); + if ( hstr == NULL ) { + fprintf( stderr, "Error: parse_syncrepl_line: " + "invalid interval \"%s\"\n", val ); + return 1; + } + *hstr++ = '\0'; + mstr = strchr( hstr, ':' ); + if ( mstr == NULL ) { + fprintf( stderr, "Error: parse_syncrepl_line: " + "invalid interval \"%s\"\n", val ); + return 1; + } + *mstr++ = '\0'; + sstr = strchr( mstr, ':' ); + if ( sstr == NULL ) { + fprintf( stderr, "Error: parse_syncrepl_line: " + "invalid interval \"%s\"\n", val ); + return 1; + } + *sstr++ = '\0'; + + dd = atoi( dstr ); + hh = atoi( hstr ); + mm = atoi( mstr ); + ss = atoi( sstr ); + if (( hh > 24 ) || ( hh < 0 ) || + ( mm > 60 ) || ( mm < 0 ) || + ( ss > 60 ) || ( ss < 0 ) || ( dd < 0 )) { + fprintf( stderr, "Error: parse_syncrepl_line: " + "invalid interval \"%s\"\n", val ); + return 1; + } + si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss; } - si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss; - if ( si->si_interval < 0 ) { fprintf( stderr, "Error: parse_syncrepl_line: " "invalid interval \"%ld\"\n", (long) si->si_interval); return 1; } + } else if ( !strncasecmp( cargv[ i ], + RETRYSTR, sizeof( RETRYSTR ) - 1 ) ) + { + char *str; + char **retry_list; + int j, k, n; + + val = cargv[ i ] + sizeof( RETRYSTR ); + retry_list = (char **) ch_calloc( 1, sizeof( char * )); + retry_list[0] = NULL; + + str2clist( &retry_list, val, " ,\t" ); + + for ( k = 0; retry_list && retry_list[k]; k++ ) ; + n = k / 2; + if ( k % 2 ) { + fprintf( stderr, + "Error: incomplete syncrepl retry list\n" ); + for ( k = 0; retry_list && retry_list[k]; k++ ) { + ch_free( retry_list[k] ); + } + ch_free( retry_list ); + exit( EXIT_FAILURE ); + } + si->si_retryinterval = (time_t *) ch_calloc( n + 1, sizeof( time_t )); + si->si_retrynum = (int *) ch_calloc( n + 1, sizeof( int )); + si->si_retrynum_init = (int *) ch_calloc( n + 1, sizeof( int )); + for ( j = 0; j < n; j++ ) { + si->si_retryinterval[j] = atoi( retry_list[j*2] ); + if ( *retry_list[j*2+1] == '+' ) { + si->si_retrynum_init[j] = -1; + si->si_retrynum[j] = -1; + j++; + break; + } else { + si->si_retrynum_init[j] = atoi( retry_list[j*2+1] ); + si->si_retrynum[j] = atoi( retry_list[j*2+1] ); + } + } + si->si_retrynum_init[j] = -2; + si->si_retrynum[j] = -2; + si->si_retryinterval[j] = 0; + + for ( k = 0; retry_list && retry_list[k]; k++ ) { + ch_free( retry_list[k] ); + } + ch_free( retry_list ); } else if ( !strncasecmp( cargv[ i ], MANAGEDSAITSTR, sizeof( MANAGEDSAITSTR ) - 1 ) ) { diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index e59a95c371..0309b877c8 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -948,7 +948,7 @@ void connection_done( Connection *c ) static void * connection_operation( void *ctx, void *arg_v ) { - int rc = SLAPD_DISCONNECT; + int rc = LDAP_OTHER; Operation *op = arg_v; SlapReply rs = {REP_RESULT}; ber_tag_t tag = op->o_tag; @@ -966,6 +966,36 @@ connection_operation( void *ctx, void *arg_v ) op->o_threadctx = ctx; + switch ( tag ) { + case LDAP_REQ_BIND: + case LDAP_REQ_UNBIND: + case LDAP_REQ_ADD: + case LDAP_REQ_DELETE: + case LDAP_REQ_MODRDN: + case LDAP_REQ_MODIFY: + case LDAP_REQ_COMPARE: + case LDAP_REQ_SEARCH: + case LDAP_REQ_ABANDON: + case LDAP_REQ_EXTENDED: + break; + default: +#ifdef NEW_LOGGING + LDAP_LOG( CONNECTION, INFO, "connection_operation: " + "conn %lu unknown LDAP request 0x%lx\n", + conn->c_connid, tag, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "connection_operation: " + "conn %lu unknown LDAP request 0x%lx\n", + conn->c_connid, tag, 0 ); +#endif + op->o_tag = LBER_ERROR; + rs.sr_err = LDAP_PROTOCOL_ERROR; + rs.sr_text = "unknown LDAP request"; + send_ldap_disconnect( op, &rs ); + rc = SLAPD_DISCONNECT; + goto operations_error; + } + if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, @@ -978,6 +1008,7 @@ connection_operation( void *ctx, void *arg_v ) #endif send_ldap_error( op, &rs, LDAP_OPERATIONS_ERROR, "SASL bind in progress" ); + rc = LDAP_OPERATIONS_ERROR; goto operations_error; } @@ -1053,29 +1084,15 @@ connection_operation( void *ctx, void *arg_v ) break; default: -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "connection_operation: conn %lu unknown LDAP request 0x%lx\n", - conn->c_connid, tag, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "unknown LDAP request 0x%lx\n", - tag, 0, 0 ); -#endif - op->o_tag = LBER_ERROR; - rs.sr_err = LDAP_PROTOCOL_ERROR; - rs.sr_text = "unknown LDAP request"; - send_ldap_disconnect( op, &rs ); - rc = -1; - break; + /* not reachable */ + assert( 0 ); } -#ifdef SLAPD_MONITOR - oldtag = tag; -#endif /* SLAPD_MONITOR */ +operations_error: if( rc == SLAPD_DISCONNECT ) tag = LBER_ERROR; -operations_error: ldap_pvt_thread_mutex_lock( &num_ops_mutex ); + num_ops_completed++; #ifdef SLAPD_MONITOR switch (oldtag) { @@ -1109,6 +1126,9 @@ operations_error: case LDAP_REQ_EXTENDED: num_ops_completed_[SLAP_OP_EXTENDED]++; break; + default: + /* not reachable */ + assert( 0 ); } #endif /* SLAPD_MONITOR */ ldap_pvt_thread_mutex_unlock( &num_ops_mutex ); @@ -1116,7 +1136,6 @@ operations_error: if ( op->o_cancel == SLAP_CANCEL_REQ ) { op->o_cancel = LDAP_TOO_LATE; } - while ( op->o_cancel != SLAP_CANCEL_NONE && op->o_cancel != SLAP_CANCEL_DONE ) { @@ -1128,14 +1147,17 @@ operations_error: ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null ); if ( op->o_cancel != SLAP_CANCEL_ACK && - ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) { + ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) + { sl_mem_detach( ctx, memctx ); - } else if (( op->o_sync_slog_size != -1 )) { + + } else if ( op->o_sync_slog_size != -1 ) { sl_mem_detach( ctx, memctx ); LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next); LDAP_STAILQ_NEXT(op, o_next) = NULL; conn->c_n_ops_executing--; conn->c_n_ops_completed++; + } else { LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next); LDAP_STAILQ_NEXT(op, o_next) = NULL; @@ -1161,9 +1183,7 @@ operations_error: } connection_resched( conn ); - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - return NULL; } @@ -1174,11 +1194,12 @@ int connection_client_setup( ldap_pvt_thread_start_t *func, void *arg ) { + int rc; Connection *c; - if ( connection_init( s, (Listener *)&dummy_list, "", "", CONN_IS_CLIENT, 0, NULL ) < 0 ) { - return -1; - } + rc = connection_init( s, (Listener *)&dummy_list, "", "", + CONN_IS_CLIENT, 0, NULL ); + if ( rc < 0 ) return -1; c = connection_get( s ); c->c_clientfunc = func; @@ -1190,15 +1211,13 @@ int connection_client_setup( } void connection_client_enable( - ber_socket_t s -) + ber_socket_t s ) { slapd_set_read( s, 1 ); } void connection_client_stop( - ber_socket_t s -) + ber_socket_t s ) { Connection *c; @@ -1333,14 +1352,13 @@ int connection_read(ber_socket_t s) rc = dnX509peerNormalize( ssl, &authid ); if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "connection_read: conn %lu unable to get TLS client DN, " - "error %d\n", c->c_connid, rc, 0 ); + LDAP_LOG( CONNECTION, INFO, "connection_read: " + "conn %lu unable to get TLS client DN, error %d\n", + c->c_connid, rc, 0 ); #else - Debug( LDAP_DEBUG_TRACE, - "connection_read(%d): unable to get TLS client DN " - "error=%d id=%lu\n", - s, rc, c->c_connid ); + Debug( LDAP_DEBUG_TRACE, "connection_read(%d): " + "unable to get TLS client DN, error=%d id=%lu\n", + s, rc, c->c_connid ); #endif } slap_sasl_external( c, c->c_tls_ssf, &authid ); @@ -1573,6 +1591,10 @@ connection_input( op->o_preread_attrs = NULL; op->o_postread_attrs = NULL; op->o_vrFilter = NULL; + /* clear state if the connection is being reused from inactive */ + if ( conn->c_conn_state == SLAP_C_INACTIVE ) { + memset( &conn->c_pagedresults_state, 0, sizeof( conn->c_pagedresults_state ) ); + } op->o_pagedresults_state = conn->c_pagedresults_state; op->o_res_ber = NULL; diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index c43a95cbf3..c1546e145f 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -918,6 +918,16 @@ static int parsePagedResults ( } else { /* Initial request. Initialize state. */ +#if 0 + if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) { + /* There's another pagedResults control on the + * same connection; reject new pagedResults controls + * (allowed by RFC2696) */ + rs->sr_text = "paged results cookie unavailable; try later"; + rc = LDAP_UNWILLING_TO_PERFORM; + goto done; + } +#endif op->o_pagedresults_state.ps_cookie = 0; op->o_pagedresults_state.ps_count = 0; } diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index d7257eaffc..084e4394db 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -2142,3 +2142,8 @@ void slapd_add_internal(ber_socket_t s, int isactive) { Listener ** slapd_get_listeners(void) { return slap_listeners; } + +void slap_wake_listener() +{ + WAKE_LISTENER(1); +} diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index 0abb6db23d..27a06ad87c 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -163,7 +163,7 @@ do_extended( op->o_protocol, 0 ,0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "requires LDAPv3" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto done; } @@ -175,7 +175,7 @@ do_extended( Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto done; } @@ -211,7 +211,7 @@ do_extended( Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 ); #endif send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); - rs->sr_err = -1; + rs->sr_err = SLAPD_DISCONNECT; goto done; } } diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 01455e8ba5..ceba658ced 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -203,7 +203,16 @@ static int test_mra_filter( MatchingRuleAssertion *mra ) { Attribute *a; - void *memctx = op ? op->o_tmpmemctx : NULL; + void *memctx; + BER_MEMFREE_FN *memfree; + + if ( op == NULL ) { + memctx = NULL; + memfree = slap_sl_free; + } else { + memctx = op->o_tmpmemctx; + memfree = op->o_tmpfree; + } if ( mra->ma_desc ) { /* @@ -267,7 +276,7 @@ static int test_mra_filter( /* check search access */ if ( !access_allowed( op, e, a->a_desc, &value, ACL_SEARCH, NULL ) ) { - op->o_tmpfree( value.bv_val, memctx ); + memfree( value.bv_val, memctx ); continue; } @@ -291,7 +300,7 @@ static int test_mra_filter( break; } } - op->o_tmpfree( value.bv_val, memctx ); + memfree( value.bv_val, memctx ); if ( rc != LDAP_SUCCESS ) return rc; } } @@ -348,7 +357,7 @@ static int test_mra_filter( if ( !access_allowed( op, e, ad, &value, ACL_SEARCH, NULL ) ) { - op->o_tmpfree( value.bv_val, memctx ); + memfree( value.bv_val, memctx ); continue; } } @@ -358,7 +367,7 @@ static int test_mra_filter( bv, &value, &text ); if ( value.bv_val != mra->ma_value.bv_val ) { - op->o_tmpfree( value.bv_val, memctx ); + memfree( value.bv_val, memctx ); } if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE; diff --git a/servers/slapd/limits.c b/servers/slapd/limits.c index b32ea0be77..c60e734068 100644 --- a/servers/slapd/limits.c +++ b/servers/slapd/limits.c @@ -23,6 +23,9 @@ #include "slap.h" +/* define to get an error if requesting limit higher than hard */ +#undef ABOVE_HARD_LIMIT_IS_ERROR + static char * limits2str( unsigned i ) { @@ -734,7 +737,7 @@ limits_parse_one( arg++; if ( strncasecmp( arg, "soft=", STRLENOF( "soft=" ) ) == 0 ) { arg += STRLENOF( "soft=" ); - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_t_soft = -1; } else { @@ -750,7 +753,7 @@ limits_parse_one( } if ( soft == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead; issue warning? */ } limit->lms_t_soft = soft; @@ -761,7 +764,7 @@ limits_parse_one( if ( strcasecmp( arg, "soft" ) == 0 ) { limit->lms_t_hard = 0; - } else if ( strcasecmp( arg, "none" ) == 0 ) { + } else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_t_hard = -1; } else { @@ -777,7 +780,7 @@ limits_parse_one( } if ( hard == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } if ( hard == 0 ) { @@ -793,7 +796,7 @@ limits_parse_one( } else if ( arg[0] == '=' ) { arg++; - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_t_soft = -1; } else { @@ -817,7 +820,7 @@ limits_parse_one( arg++; if ( strncasecmp( arg, "soft=", STRLENOF( "soft=" ) ) == 0 ) { arg += STRLENOF( "soft=" ); - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_soft = -1; } else { @@ -833,7 +836,7 @@ limits_parse_one( } if ( soft == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } limit->lms_s_soft = soft; @@ -844,7 +847,7 @@ limits_parse_one( if ( strcasecmp( arg, "soft" ) == 0 ) { limit->lms_s_hard = 0; - } else if ( strcasecmp( arg, "none" ) == 0 ) { + } else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_hard = -1; } else { @@ -860,7 +863,7 @@ limits_parse_one( } if ( hard == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } if ( hard == 0 ) { @@ -872,7 +875,7 @@ limits_parse_one( } else if ( strncasecmp( arg, "unchecked=", STRLENOF( "unchecked=" ) ) == 0 ) { arg += STRLENOF( "unchecked=" ); - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_unchecked = -1; } else if ( strcasecmp( arg, "disabled" ) == 0 ) { @@ -891,7 +894,7 @@ limits_parse_one( } if ( unchecked == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } limit->lms_s_unchecked = unchecked; @@ -902,7 +905,7 @@ limits_parse_one( if ( strcasecmp( arg, "noEstimate" ) == 0 ) { limit->lms_s_pr_hide = 1; - } else if ( strcasecmp( arg, "none" ) == 0 ) { + } else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_pr = -1; } else { @@ -918,7 +921,7 @@ limits_parse_one( } if ( pr == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } limit->lms_s_pr = pr; @@ -927,7 +930,7 @@ limits_parse_one( } else if ( strncasecmp( arg, "prtotal=", STRLENOF( "prtotal=" ) ) == 0 ) { arg += STRLENOF( "prtotal=" ); - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_pr_total = -1; } else if ( strcasecmp( arg, "disabled" ) == 0 ) { @@ -950,7 +953,7 @@ limits_parse_one( } if ( total == -1 ) { - /* FIXME: use "none" instead */ + /* FIXME: use "unlimited" instead */ } if ( total == 0 ) { @@ -966,7 +969,7 @@ limits_parse_one( } else if ( arg[0] == '=' ) { arg++; - if ( strcasecmp( arg, "none" ) == 0 ) { + if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) { limit->lms_s_soft = -1; } else { @@ -995,7 +998,20 @@ limits_check( Operation *op, SlapReply *rs ) assert( rs ); /* FIXME: should this be always true? */ assert( op->o_tag == LDAP_REQ_SEARCH); - + + /* protocol only allows 0..maxInt; + * + * internal searches: + * - may use SLAP_NO_LIMIT ( = -1 ) to indicate no limits; + * - should use slimit = N and tlimit = SLAP_NO_LIMIT to + * indicate searches that should return exactly N matches, + * and handle errors thru a callback (see for instance + * slap_sasl_match() and slap_sasl2dn()) + */ + if ( op->ors_tlimit == SLAP_NO_LIMIT && op->ors_slimit == SLAP_NO_LIMIT ) { + return 0; + } + /* allow root to set no limit */ if ( be_isroot( op ) ) { op->ors_limit = NULL; @@ -1022,18 +1038,27 @@ limits_check( Operation *op, SlapReply *rs ) } else { if ( op->ors_limit->lms_t_hard == 0 ) { if ( op->ors_limit->lms_t_soft > 0 - && ( op->ors_tlimit < 0 || op->ors_tlimit > op->ors_limit->lms_t_soft ) ) { + && ( op->ors_tlimit > op->ors_limit->lms_t_soft ) ) { op->ors_tlimit = op->ors_limit->lms_t_soft; } } else if ( op->ors_limit->lms_t_hard > 0 ) { - if ( op->ors_tlimit < 0 || op->ors_tlimit > op->ors_limit->lms_t_hard ) { +#ifdef ABOVE_HARD_LIMIT_IS_ERROR + if ( op->ors_tlimit == SLAP_MAX_LIMIT ) { + op->ors_tlimit = op->ors_limit->lms_t_hard; + + } else if ( op->ors_tlimit > op->ors_limit->lms_t_hard ) { /* error if exceeding hard limit */ rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; return -1; } +#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */ + if ( op->ors_tlimit > op->ors_limit->lms_t_hard ) { + op->ors_tlimit = op->ors_limit->lms_t_hard; + } +#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */ } } @@ -1082,13 +1107,22 @@ limits_check( Operation *op, SlapReply *rs ) } if ( pr_total == -1 ) { - slimit = -1; + if ( op->ors_slimit == 0 || op->ors_slimit == SLAP_MAX_LIMIT ) { + slimit = -1; - } else if ( pr_total > 0 && ( op->ors_slimit == SLAP_NO_LIMIT || op->ors_slimit > pr_total ) ) { + } else { + slimit = op->ors_slimit - op->o_pagedresults_state.ps_count; + } + +#ifdef ABOVE_HARD_LIMIT_IS_ERROR + } else if ( pr_total > 0 && op->ors_slimit != SLAP_MAX_LIMIT + && ( op->ors_slimit == SLAP_NO_LIMIT || op->ors_slimit > pr_total ) ) + { rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; return -1; +#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */ } else { /* if no limit is required, use soft limit */ @@ -1097,15 +1131,20 @@ limits_check( Operation *op, SlapReply *rs ) /* first round of pagedResults: set count to any appropriate limit */ - /* if the limit is set, check that it does not violate any limit */ - if ( op->ors_slimit > 0 ) { - slimit2 = op->ors_slimit; + /* if the limit is set, check that it does not violate any server-side limit */ +#ifdef ABOVE_HARD_LIMIT_IS_ERROR + if ( op->ors_slimit == SLAP_MAX_LIMIT ) { + slimit2 = op->ors_slimit = pr_total; +#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */ + if ( op->ors_slimit == SLAP_MAX_LIMIT || op->ors_slimit > pr_total ) { + slimit2 = op->ors_slimit = pr_total; +#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */ } else if ( op->ors_slimit == 0 ) { slimit2 = pr_total; } else { - slimit2 = -1; + slimit2 = op->ors_slimit; } total = slimit2 - op->o_pagedresults_state.ps_count; @@ -1140,7 +1179,7 @@ limits_check( Operation *op, SlapReply *rs ) /* if got any limit, use it */ if ( slimit != -2 ) { - if ( op->ors_slimit <= 0 ) { + if ( op->ors_slimit == 0 ) { op->ors_slimit = slimit; } else if ( slimit > 0 ) { @@ -1173,13 +1212,22 @@ limits_check( Operation *op, SlapReply *rs ) /* explicit hard limit: error if violated */ } else if ( op->ors_limit->lms_s_hard > 0 ) { - if ( op->ors_slimit > op->ors_limit->lms_s_hard ) { +#ifdef ABOVE_HARD_LIMIT_IS_ERROR + if ( op->ors_slimit == SLAP_MAX_LIMIT ) { + op->ors_slimit = op->ors_limit->lms_s_hard; + + } else if ( op->ors_slimit > op->ors_limit->lms_s_hard ) { /* if limit exceeds hard, error */ rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; return -1; } +#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */ + if ( op->ors_slimit > op->ors_limit->lms_s_hard ) { + op->ors_slimit = op->ors_limit->lms_s_hard; + } +#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */ } } diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c index 78ebaa7c60..42fd967ec3 100644 --- a/servers/slapd/oc.c +++ b/servers/slapd/oc.c @@ -469,6 +469,7 @@ oc_add( } if ( code != 0 ) return code; + if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP; code = oc_create_required( soc, soc->soc_at_oids_must, &op, err ); if ( code != 0 ) return code; @@ -476,7 +477,7 @@ oc_add( code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err ); if ( code != 0 ) return code; - if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP; + if( user && op ) return SLAP_SCHERR_CLASS_BAD_USAGE; code = oc_insert(soc,err); return code; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 357bcf4809..a6f349bf32 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -420,6 +420,7 @@ LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, int wasactive, int wake LDAP_SLAPD_F (RETSIGTYPE) slap_sig_shutdown LDAP_P((int sig)); LDAP_SLAPD_F (RETSIGTYPE) slap_sig_wake LDAP_P((int sig)); +LDAP_SLAPD_F (void) slap_wake_listener LDAP_P((void)); LDAP_SLAPD_F (void) slapd_set_write LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_F (void) slapd_clr_write LDAP_P((ber_socket_t s, int wake)); diff --git a/servers/slapd/result.c b/servers/slapd/result.c index f591b5e6c2..cef4daee4b 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -524,7 +524,6 @@ send_ldap_disconnect( Operation *op, SlapReply *rs ) rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL ); #endif - if ( op->o_protocol < LDAP_VERSION3 ) { rs->sr_rspoid = NULL; rs->sr_tag = req2res( op->o_tag ); @@ -614,11 +613,15 @@ slap_send_ldap_result( Operation *op, SlapReply *rs ) */ if ( op->o_pb != NULL ) { slapi_int_pblock_set_operation( op->o_pb, op ); - slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err ); - slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text ); - slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, + (void *)rs->sr_err ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, + (void *)rs->sr_text ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, + (void *)rs->sr_matched ); - (void) slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, op->o_pb ); + (void) slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, + op->o_pb ); } #endif /* LDAP_SLAPI */ @@ -929,12 +932,12 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) { #ifdef NEW_LOGGING LDAP_LOG( ACL, INFO, - "send_search_entry: conn %lu access to attribute %s not " + "send_search_entry: conn %lu access to attribute %s not " "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 ); #else - Debug( LDAP_DEBUG_ACL, "acl: " - "access to attribute %s not allowed\n", - desc->ad_cname.bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "send_search_entry: " + "conn %lu access to attribute %s not allowed\n", + op->o_connid, desc->ad_cname.bv_val, 0 ); #endif continue; } @@ -949,7 +952,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) #endif if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encoding description error"); + send_ldap_error( op, rs, LDAP_OTHER, + "encoding description error"); goto error_return; } finish = 1; @@ -963,13 +967,13 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) #ifdef NEW_LOGGING LDAP_LOG( ACL, INFO, "send_search_entry: conn %lu " - "access to attribute %s, value %d not allowed\n", + "access to attribute %s, value #%d not allowed\n", op->o_connid, desc->ad_cname.bv_val, i ); #else Debug( LDAP_DEBUG_ACL, - "acl: access to attribute %s, " - "value %d not allowed\n", - desc->ad_cname.bv_val, i, 0 ); + "send_search_entry: conn %lu " + "access to attribute %s, value #%d not allowed\n", + op->o_connid, desc->ad_cname.bv_val, i ); #endif continue; @@ -992,7 +996,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) #endif if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encoding description error"); + send_ldap_error( op, rs, LDAP_OTHER, + "encoding description error"); goto error_return; } } @@ -1129,8 +1134,10 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "access to attribute %s not allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 ); #else - Debug( LDAP_DEBUG_ACL, "send_search_entry: access to attribute %s " - "not allowed\n", desc->ad_cname.bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ACL, + "send_search_entry: conn %lu " + "access to attribute %s not allowed\n", + op->o_connid, desc->ad_cname.bv_val, 0 ); #endif continue; @@ -1147,7 +1154,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) #endif if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encoding description error" ); + send_ldap_error( op, rs, LDAP_OTHER, + "encoding description error" ); attrs_free( aa ); goto error_return; } @@ -1232,9 +1240,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) { rc = compute_evaluator( &ctx, anp->an_name.bv_val, rs->sr_entry, slapi_int_compute_output_ber ); - if ( rc == 1 ) { - break; - } + if ( rc == 1 ) break; } } else { /* @@ -1664,7 +1670,14 @@ int slap_read_controls( c.ldctl_oid = oid->bv_val; c.ldctl_iscritical = 0; - *ctrl = sl_calloc( 1, sizeof(LDAPControl), NULL ); + if ( ctrl == NULL ) { + /* first try */ + *ctrl = (LDAPControl *) sl_calloc( 1, sizeof(LDAPControl), NULL ); + } else { + /* retry: free previous try */ + slap_sl_free( (*ctrl)->ldctl_value.bv_val, &op->o_tmpmemctx ); + } + **ctrl = c; return LDAP_SUCCESS; } diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 7a26363f5c..b28477384c 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -738,38 +738,172 @@ bitStringValidate( return LDAP_SUCCESS; } +/* + * Syntax is [RFC2252]: + * + +6.3. Bit String + + ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) + + Values in this syntax are encoded according to the following BNF: + + bitstring = "'" *binary-digit "'B" + + binary-digit = "0" / "1" + + ... + +6.21. Name And Optional UID + + ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' ) + + Values in this syntax are encoded according to the following BNF: + + NameAndOptionalUID = DistinguishedName [ "#" bitstring ] + + Although the '#' character may occur in a string representation of a + distinguished name, no additional special quoting is done. This + syntax has been added subsequent to RFC 1778. + + Example: + + 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B + + * + * draft-ietf-ldapbis-syntaxes-xx.txt says: + * + +3.3.2. Bit String + + A value of the Bit String syntax is a sequence of binary digits. The + LDAP-specific encoding of a value of this syntax is defined by the + following ABNF: + + BitString = SQUOTE *binary-digit SQUOTE "B" + + binary-digit = "0" / "1" + + The rule is defined in [MODELS]. + + Example: + '0101111101'B + + The LDAP definition for the Bit String syntax is: + + ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) + + This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1]. + + ... + +3.3.21. Name and Optional UID + + A value of the Name and Optional UID syntax is the distinguished name + [MODELS] of an entity optionally accompanied by a unique identifier + that serves to differentiate the entity from others with an identical + distinguished name. + + The LDAP-specific encoding of a value of this syntax is defined by + the following ABNF: + + NameAndOptionalUID = distinguishedName [ SHARP BitString ] + + The rule is defined in Section 3.3.2. The + rule is defined in [LDAPDN]. The rule is + defined in [MODELS]. + + Note that although the '#' character may occur in the string + representation of a distinguished name, no additional escaping of + this character is performed when a is encoded in + a . + + Example: + 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B + + The LDAP definition for the Name and Optional UID syntax is: + + ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' ) + + This syntax corresponds to the NameAndOptionalUID ASN.1 type from + [X.520]. + + * + * draft-ietf-ldapbis-models-xx.txt [MODELS] says: + * + +1.4. Common ABNF Productions + + ... + SHARP = %x23 ; octothorpe (or sharp sign) ("#") + ... + SQUOTE = %x27 ; single quote ("'") + ... + + * + * Note: normalization strips any leading "0"s, unless the + * bit string is exactly "'0'B", so the normalized example, + * in slapd, would result in + * + * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B + * + * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP, + * i.e. "#", doesn't have to be escaped except when at the + * beginning of a value, the definition of Name and Optional + * UID appears to be flawed, because there is no clear means + * to determine whether the UID part is present or not. + * + * Example: + * + * cn=Someone,dc=example,dc=com#'1'B + * + * could be either a NameAndOptionalUID with trailing UID, i.e. + * + * DN = "cn=Someone,dc=example,dc=com" + * UID = "'1'B" + * + * or a NameAndOptionalUID with no trailing UID, and the AVA + * in the last RDN made of + * + * attributeType = dc + * attributeValue = com#'1'B + * + * in fact "com#'1'B" is a valid IA5 string. + * + * As a consequence, current slapd code assumes that the + * presence of portions of a BitString at the end of the string + * representation of a NameAndOptionalUID means a BitString + * is expected, and cause an error otherwise. This is quite + * arbitrary, and might change in the future. + */ + + static int nameUIDValidate( Syntax *syntax, struct berval *in ) { int rc; - struct berval dn; + struct berval dn, uid; if( in->bv_len == 0 ) return LDAP_SUCCESS; ber_dupbv( &dn, in ); if( !dn.bv_val ) return LDAP_OTHER; - if( dn.bv_val[dn.bv_len-1] == 'B' - && dn.bv_val[dn.bv_len-2] == '\'' ) - { - /* assume presence of optional UID */ - ber_len_t i; + /* if there's a "#", try bitStringValidate()... */ + uid.bv_val = strrchr( dn.bv_val, '#' ); + if ( uid.bv_val ) { + uid.bv_val++; + uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val ); - for(i=dn.bv_len-3; i>1; i--) { - if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) { - break; - } + rc = bitStringValidate( NULL, &uid ); + if ( rc == LDAP_SUCCESS ) { + /* in case of success, trim the UID, + * otherwise treat it as part of the DN */ + dn.bv_len -= uid.bv_len + 1; + uid.bv_val[-1] = '\0'; } - if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) { - ber_memfree( dn.bv_val ); - return LDAP_INVALID_SYNTAX; - } - - /* trim the UID to allow use of dnValidate */ - dn.bv_val[i-1] = '\0'; - dn.bv_len = i-1; } rc = dnValidate( NULL, &dn ); @@ -802,38 +936,52 @@ nameUIDPretty( return LDAP_INVALID_SYNTAX; } else { - int rc; - struct berval dnval = *val; - struct berval uidval = BER_BVNULL; + int rc; + struct berval dnval = *val; + struct berval uidval = BER_BVNULL; - if( val->bv_val[val->bv_len-1] == 'B' - && val->bv_val[val->bv_len-2] == '\'' ) - { - uidval.bv_val=strrchr( val->bv_val, '#' ); - if( uidval.bv_val ) { - dnval.bv_len = uidval.bv_val - dnval.bv_val; - uidval.bv_len = val->bv_len - dnval.bv_len; + uidval.bv_val = strrchr( val->bv_val, '#' ); + if ( uidval.bv_val ) { + uidval.bv_val++; + uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val ); - uidval.bv_len--; - uidval.bv_val++; + rc = bitStringValidate( NULL, &uidval ); + + if ( rc == LDAP_SUCCESS ) { + ber_dupbv_x( &dnval, val, ctx ); + dnval.bv_len -= uidval.bv_len + 1; + dnval.bv_val[dnval.bv_len] = '\0'; + + } else { + uidval.bv_val = NULL; } } rc = dnPretty( syntax, &dnval, out, ctx ); - if( rc != LDAP_SUCCESS ) return rc; + if ( dnval.bv_val != val->bv_val ) { + slap_sl_free( dnval.bv_val, ctx ); + } + if( rc != LDAP_SUCCESS ) { + return rc; + } if( uidval.bv_val ) { - char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx ); - int i, c, got1; + int i, c, got1; + char *tmp; + + tmp = sl_realloc( out->bv_val, out->bv_len + + STRLENOF( "#" ) + uidval.bv_len + 1, + ctx ); if( tmp == NULL ) { ber_memfree_x( out->bv_val, ctx ); return LDAP_OTHER; } out->bv_val = tmp; out->bv_val[out->bv_len++] = '#'; + out->bv_val[out->bv_len++] = '\''; got1 = uidval.bv_len < sizeof("'0'B"); - for(i=0; ibv_val[out->bv_len++] = c; + break; } } + out->bv_val[out->bv_len++] = '\''; + out->bv_val[out->bv_len++] = 'B'; out->bv_val[out->bv_len] = '\0'; } } @@ -880,22 +1030,18 @@ uniqueMemberNormalize( } else { struct berval uid = BER_BVNULL; - if( out.bv_val[out.bv_len-1] == 'B' - && out.bv_val[out.bv_len-2] == '\'' ) - { - /* assume presence of optional UID */ - uid.bv_val = strrchr( out.bv_val, '#' ); + uid.bv_val = strrchr( out.bv_val, '#' ); + if ( uid.bv_val ) { + uid.bv_val++; + uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val ); - if( uid.bv_val == NULL ) { - sl_free( out.bv_val, ctx ); - return LDAP_INVALID_SYNTAX; + rc = bitStringValidate( NULL, &uid ); + if ( rc == LDAP_SUCCESS ) { + uid.bv_val[-1] = '\0'; + out.bv_len -= uid.bv_len + 1; + } else { + uid.bv_val = NULL; } - - uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val); - out.bv_len -= uid.bv_len--; - - /* temporarily trim the UID */ - *(uid.bv_val++) = '\0'; } rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx ); @@ -905,9 +1051,18 @@ uniqueMemberNormalize( return LDAP_INVALID_SYNTAX; } - if( uid.bv_len ) { - normalized->bv_val = ch_realloc( normalized->bv_val, - normalized->bv_len + uid.bv_len + sizeof("#") ); + if( uid.bv_val ) { + char *tmp; + + tmp = ch_realloc( normalized->bv_val, + normalized->bv_len + uid.bv_len + + STRLENOF("#") + 1 ); + if ( tmp == NULL ) { + ber_memfree_x( normalized->bv_val, ctx ); + return LDAP_OTHER; + } + + normalized->bv_val = tmp; /* insert the separator */ normalized->bv_val[normalized->bv_len++] = '#'; @@ -943,51 +1098,49 @@ uniqueMemberMatch( struct berval valueDN = BER_BVNULL; struct berval valueUID = BER_BVNULL; - if( asserted->bv_len != 0 ) { + if( !BER_BVISEMPTY( asserted ) ) { assertedDN = *asserted; - if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B' - && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' ) - { - /* assume presence of optional UID */ - assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); - - if( assertedUID.bv_val == NULL ) { - return LDAP_INVALID_SYNTAX; - } + assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); + if ( !BER_BVISNULL( &assertedUID ) ) { + assertedUID.bv_val++; + assertedUID.bv_len = assertedDN.bv_len + - ( assertedUID.bv_val - assertedDN.bv_val ); - assertedUID.bv_len = assertedDN.bv_len - - (assertedUID.bv_val - assertedDN.bv_val); - assertedDN.bv_len -= assertedUID.bv_len--; + if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { + assertedDN.bv_len -= assertedUID.bv_len + 1; - /* trim the separator */ - assertedUID.bv_val++; + } else { + BER_BVZERO( &assertedUID ); + } } } - if( value->bv_len != 0 ) { + if ( !BER_BVISEMPTY( value ) ) { valueDN = *value; - if( valueDN.bv_val[valueDN.bv_len-1] == 'B' - && valueDN.bv_val[valueDN.bv_len-2] == '\'' ) - { - /* assume presence of optional UID */ - valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); - - if( valueUID.bv_val == NULL ) { - return LDAP_INVALID_SYNTAX; - } + valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); + if ( !BER_BVISNULL( &valueUID ) ) { + valueUID.bv_val++; + valueUID.bv_len = valueDN.bv_len + - ( valueUID.bv_val - valueDN.bv_val ); - valueUID.bv_len = valueDN.bv_len - - (assertedUID.bv_val - assertedDN.bv_val); - valueDN.bv_len -= valueUID.bv_len--; + if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) { + valueDN.bv_len -= valueUID.bv_len + 1; - /* trim the separator */ - valueUID.bv_val++; + } else { + BER_BVZERO( &valueUID ); + } } } if( valueUID.bv_len && assertedUID.bv_len ) { + match = valueUID.bv_len - assertedUID.bv_len; + if ( match ) { + *matchp = match; + return LDAP_SUCCESS; + } + match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len ); if( match ) { *matchp = match; @@ -1931,7 +2084,8 @@ numericStringNormalize( * Integer conversion macros that will use the largest available * type. */ -#if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG) +#if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \ + && defined(LLONG_MIN) && defined(HAVE_LONG_LONG) # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) # define SLAP_LONG_MAX LLONG_MAX # define SLAP_LONG_MIN LLONG_MIN @@ -1956,13 +2110,16 @@ integerBitAndMatch( /* safe to assume integers are NUL terminated? */ lValue = SLAP_STRTOL(value->bv_val, NULL, 10); - if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) { + if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && + errno == ERANGE ) + { return LDAP_CONSTRAINT_VIOLATION; } - lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10); - if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) - && errno == ERANGE ) + lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, + NULL, 10); + if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && + errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; } @@ -1992,8 +2149,8 @@ integerBitOrMatch( lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, NULL, 10); - if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) - && errno == ERANGE ) + if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && + errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; } @@ -2024,9 +2181,7 @@ serialNumberAndIssuerValidate( /* validate serial number (strict for now) */ for( n=0; n < sn.bv_len; n++ ) { - if( !ASCII_DIGIT(sn.bv_val[n]) ) { - return LDAP_INVALID_SYNTAX; - } + if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX; } /* validate DN */ @@ -2078,9 +2233,7 @@ serialNumberAndIssuerPretty( sn.bv_len -= n; for( n=0; n < sn.bv_len; n++ ) { - if( !ASCII_DIGIT(sn.bv_val[n]) ) { - return LDAP_INVALID_SYNTAX; - } + if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX; } /* pretty DN */ diff --git a/servers/slapd/schema_prep.c b/servers/slapd/schema_prep.c index 2835e2a93e..9ebb77a1e8 100644 --- a/servers/slapd/schema_prep.c +++ b/servers/slapd/schema_prep.c @@ -57,31 +57,26 @@ oidValidate( } } else { + int sep = 0; while( OID_LEADCHAR( val.bv_val[0] ) ) { - if ( val.bv_len == 1 ) { - return LDAP_SUCCESS; - } - - if ( val.bv_val[0] == '0' ) { - break; - } - val.bv_val++; val.bv_len--; - while ( OID_LEADCHAR( val.bv_val[0] )) { - val.bv_val++; - val.bv_len--; - - if ( val.bv_len == 0 ) { - return LDAP_SUCCESS; + if ( val.bv_val[-1] != '0' ) { + while ( OID_LEADCHAR( val.bv_val[0] )) { + val.bv_val++; + val.bv_len--; } } - if( !OID_SEPARATOR( val.bv_val[0] )) { - break; + if( val.bv_len == 0 ) { + if( sep == 0 ) break; + return LDAP_SUCCESS; } + if( !OID_SEPARATOR( val.bv_val[0] )) break; + + sep++; val.bv_val++; val.bv_len--; } diff --git a/servers/slapd/search.c b/servers/slapd/search.c index c35ef511a2..41984eac86 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -47,8 +47,8 @@ static void call_search_postop_plugins( Operation *op ); int do_search( Operation *op, /* info about the op to which we're responding */ - SlapReply *rs /* all the response data we'll send */ -) { + SlapReply *rs /* all the response data we'll send */ ) +{ struct berval base = BER_BVNULL; ber_len_t siz, off, i; int manageDSAit; @@ -97,6 +97,16 @@ do_search( goto return_results; } + if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) { + send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" ); + goto return_results; + } + + if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) { + send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" ); + goto return_results; + } + switch( op->ors_scope ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: @@ -150,6 +160,7 @@ do_search( if( rs->sr_err == SLAPD_DISCONNECT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; send_ldap_disconnect( op, rs ); + rs->sr_err = SLAPD_DISCONNECT; } else { send_ldap_result( op, rs ); } @@ -412,19 +423,24 @@ do_search( #endif /* LDAP_SLAPI */ return_results:; + if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) return rs->sr_err; + if ( ( op->o_sync_slog_size != -1 ) ) return rs->sr_err; - if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) - return rs->sr_err; - - if ( ( op->o_sync_slog_size != -1 ) ) - return rs->sr_err; - - if( op->o_req_dn.bv_val != NULL) sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); - if( op->o_req_ndn.bv_val != NULL) sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); + if( !BER_BVISNULL( &op->o_req_dn ) ) { + slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); + } + if( !BER_BVISNULL( &op->o_req_ndn ) ) { + slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); + } - if( op->ors_filterstr.bv_val != NULL) op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); + if( !BER_BVISNULL( &op->ors_filterstr ) ) { + op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); + } if( op->ors_filter != NULL) filter_free_x( op, op->ors_filter ); - if( op->ors_attrs != NULL ) op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); + if( op->ors_attrs != NULL ) { + op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); + } + #ifdef LDAP_SLAPI if( attrs != NULL) op->o_tmpfree( attrs, op->o_tmpmemctx ); #endif /* LDAP_SLAPI */ diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 9eb6795e7a..96ea47c236 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1302,6 +1302,7 @@ struct slap_limits_set { /* Note: this is different from LDAP_NO_LIMIT (0); slapd internal use only */ #define SLAP_NO_LIMIT -1 +#define SLAP_MAX_LIMIT 2147483647 struct slap_limits { unsigned lm_flags; /* type of pattern */ @@ -1395,6 +1396,9 @@ typedef struct syncinfo_s { char **si_attrs; int si_type; time_t si_interval; + time_t *si_retryinterval; + int *si_retrynum_init; + int *si_retrynum; struct sync_cookie si_syncCookie; int si_manageDSAit; int si_slimit; diff --git a/servers/slapd/slapd.conf b/servers/slapd/slapd.conf index f7f251113d..2531929648 100644 --- a/servers/slapd/slapd.conf +++ b/servers/slapd/slapd.conf @@ -49,7 +49,7 @@ argsfile %LOCALSTATEDIR%/run/slapd.args # rootdn can always read and write EVERYTHING! ####################################################################### -# ldbm database definitions +# BDB database definitions ####################################################################### database bdb diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c index 1a082f4257..538651ac16 100644 --- a/servers/slapd/slapi/slapi_utils.c +++ b/servers/slapd/slapi/slapi_utils.c @@ -3584,7 +3584,7 @@ int slapi_int_compute_output_ber(computed_attr_context *c, Slapi_Attr *a, Slapi_ return 1; } - if ( !c->cac_attrsonly ) { + if ( !c->cac_attrsonly && a->a_vals != NULL ) { for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { if ( !access_allowed( op, e, desc, &a->a_vals[i], ACL_READ, &c->cac_acl_state)) { diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 9ed5606acc..94f1e5c3d3 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -153,12 +153,12 @@ ldap_sync_search( ctrls[1] = NULL; } - timeout.tv_sec = si->si_tlimit > 0 ? si->si_tlimit : 1; + timeout.tv_sec = si->si_tlimit; timeout.tv_usec = 0; rc = ldap_search_ext( si->si_ld, si->si_base.bv_val, si->si_scope, si->si_filterstr.bv_val, si->si_attrs, si->si_attrsonly, - ctrls, NULL, si->si_tlimit < 0 ? NULL : &timeout, + ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL, si->si_slimit, &msgid ); ber_free_buf( ber ); @@ -807,6 +807,7 @@ do_syncrepl( int first = 0; int dostop = 0; ber_socket_t s; + int i, defer = 1; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 ); @@ -869,7 +870,7 @@ do_syncrepl( arg ); } else { connection_client_enable( s ); - } + } } else if ( !first ) { dostop = 1; } @@ -885,6 +886,7 @@ do_syncrepl( * 4) for Persist and Success, reschedule to defer */ ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex ); + if ( ldap_pvt_runqueue_isrunning( &syncrepl_rq, rtask )) { ldap_pvt_runqueue_stoptask( &syncrepl_rq, rtask ); } @@ -893,17 +895,35 @@ do_syncrepl( connection_client_stop( s ); } - if ( rc && rc != LDAP_SERVER_DOWN ) { - ldap_pvt_runqueue_remove( &syncrepl_rq, rtask ); + if ( rc == LDAP_SUCCESS ) { + if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) { + defer = 0; + } + rtask->interval.tv_sec = si->si_interval; + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, defer ); + if ( si->si_retrynum ) { + for ( i = 0; si->si_retrynum_init[i] != -2; i++ ) { + si->si_retrynum[i] = si->si_retrynum_init[i]; + } + si->si_retrynum[i] = -2; + } } else { - if ( rc == LDAP_SERVER_DOWN || - si->si_type == LDAP_SYNC_REFRESH_ONLY ) { - rc = 0; - } else { - rc = 1; + for ( i = 0; si->si_retrynum && si->si_retrynum[i] <= 0; i++ ) { + if ( si->si_retrynum[i] == -1 || si->si_retrynum[i] == -2 ) + break; + } + + if ( !si->si_retrynum || si->si_retrynum[i] == -2 ) { + ldap_pvt_runqueue_remove( &syncrepl_rq, rtask ); + } else if ( si->si_retrynum[i] >= -1 ) { + if ( si->si_retrynum[i] > 0 ) + si->si_retrynum[i]--; + rtask->interval.tv_sec = si->si_retryinterval[i]; + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 ); + slap_wake_listener(); } - ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, rc ); } + ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex ); return NULL; @@ -1061,7 +1081,10 @@ syncrepl_entry( struct berval syncUUID_strrep = BER_BVNULL; struct berval uuid_bv = BER_BVNULL; - SlapReply rs = {REP_RESULT}; + SlapReply rs_search = {REP_RESULT}; + SlapReply rs_delete = {REP_RESULT}; + SlapReply rs_add = {REP_RESULT}; + SlapReply rs_modify = {REP_RESULT}; Filter f = {0}; AttributeAssertion ava = {0}; int rc = LDAP_SUCCESS; @@ -1108,6 +1131,10 @@ syncrepl_entry( op->o_req_dn = si->si_base; op->o_req_ndn = si->si_base; + op->o_time = slap_get_time(); + op->ors_tlimit = SLAP_NO_LIMIT; + op->ors_slimit = 1; + /* set callback function */ op->o_callback = &cb; cb.sc_response = dn_callback; @@ -1115,8 +1142,8 @@ syncrepl_entry( si->si_syncUUID_ndn.bv_val = NULL; - if ( limits_check( op, &rs ) == 0 ) { - rc = be->be_search( op, &rs ); + if ( limits_check( op, &rs_search ) == 0 ) { + rc = be->be_search( op, &rs_search ); } if ( op->ors_filterstr.bv_val ) { @@ -1126,8 +1153,7 @@ syncrepl_entry( cb.sc_response = null_callback; cb.sc_private = si; - if ( rc == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val ) - { + if ( rs_search.sr_err == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val ) { char *subseq_ptr; if ( syncstate != LDAP_SYNC_DELETE ) { @@ -1144,7 +1170,7 @@ syncrepl_entry( op->o_req_dn = si->si_syncUUID_ndn; op->o_req_ndn = si->si_syncUUID_ndn; op->o_tag = LDAP_REQ_DELETE; - rc = be->be_delete( op, &rs ); + rc = be->be_delete( op, &rs_delete ); org_req_dn = op->o_req_dn; org_req_ndn = op->o_req_ndn; @@ -1155,8 +1181,7 @@ syncrepl_entry( op->o_ndn = op->o_bd->be_rootndn; op->o_managedsait = 1; - while ( rs.sr_err == LDAP_SUCCESS && - op->o_delete_glue_parent ) { + while ( rs_delete.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) { op->o_delete_glue_parent = 0; if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) { slap_callback cb = { NULL }; @@ -1165,7 +1190,7 @@ syncrepl_entry( op->o_req_dn = pdn; op->o_req_ndn = pdn; op->o_callback = &cb; - op->o_bd->be_delete( op, &rs ); + op->o_bd->be_delete( op, &rs_delete ); } else { break; } @@ -1184,10 +1209,10 @@ syncrepl_entry( switch ( syncstate ) { case LDAP_SYNC_ADD: case LDAP_SYNC_MODIFY: - if ( rc == LDAP_SUCCESS || - rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT || - rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) + if ( rs_search.sr_err == LDAP_SUCCESS || + rs_search.sr_err == LDAP_REFERRAL || + rs_search.sr_err == LDAP_NO_SUCH_OBJECT || + rs_search.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF ) { attr_delete( &e->e_attrs, slap_schema.si_ad_entryUUID ); attr_merge_one( e, slap_schema.si_ad_entryUUID, @@ -1197,10 +1222,12 @@ syncrepl_entry( op->ora_e = e; op->o_req_dn = e->e_name; op->o_req_ndn = e->e_nname; - rc = be->be_add( op, &rs ); - if ( rc != LDAP_SUCCESS ) { - if ( rc == LDAP_ALREADY_EXISTS ) { + rc = be->be_add( op, &rs_add ); + + if ( rs_add.sr_err != LDAP_SUCCESS ) { + if ( rs_add.sr_err == LDAP_ALREADY_EXISTS && + rs_search.sr_err != LDAP_NO_SUCH_OBJECT ) { Modifications *mod; Modifications *modtail = modlist; @@ -1223,21 +1250,22 @@ syncrepl_entry( op->o_req_dn = e->e_name; op->o_req_ndn = e->e_nname; - rc = be->be_modify( op, &rs ); - if ( rc != LDAP_SUCCESS ) { + rc = be->be_modify( op, &rs_modify ); + if ( rs_modify.sr_err != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "syncrepl_entry : be_modify failed (%d)\n", - rc, 0, 0 ); + rs_modify.sr_err, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "syncrepl_entry : be_modify failed (%d)\n", - rc, 0, 0 ); + rs_modify.sr_err, 0, 0 ); #endif } ret = 1; goto done; - } else if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT ) { + } else if ( rs_modify.sr_err == LDAP_REFERRAL || + rs_modify.sr_err == LDAP_NO_SUCH_OBJECT ) { syncrepl_add_glue( op, e ); ret = 0; goto done; @@ -1245,11 +1273,11 @@ syncrepl_entry( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "syncrepl_entry : be_add failed (%d)\n", - rc, 0, 0 ); + rs_add.sr_err, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "syncrepl_entry : be_add failed (%d)\n", - rc, 0, 0 ); + rs_add.sr_err, 0, 0 ); #endif ret = 1; goto done; @@ -1262,10 +1290,12 @@ syncrepl_entry( } else { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 ); + "syncrepl_entry : be_search failed (%d)\n", + rs_search.sr_err, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 ); + "syncrepl_entry : be_search failed (%d)\n", + rs_search.sr_err, 0, 0 ); #endif ret = 1; goto done; @@ -1313,7 +1343,9 @@ syncrepl_del_nonpresent( { Backend* be = op->o_bd; slap_callback cb = { NULL }; - SlapReply rs = {REP_RESULT}; + SlapReply rs_search = {REP_RESULT}; + SlapReply rs_delete = {REP_RESULT}; + SlapReply rs_modify = {REP_RESULT}; struct nonpresent_entry *np_list, *np_prev; int rc; Modifications *ml; @@ -1340,8 +1372,9 @@ syncrepl_del_nonpresent( op->o_tag = LDAP_REQ_SEARCH; op->ors_scope = si->si_scope; op->ors_deref = LDAP_DEREF_NEVER; - op->ors_slimit = 0; - op->ors_tlimit = 0; + op->o_time = slap_get_time(); + op->ors_tlimit = SLAP_NO_LIMIT; + op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrsonly = 0; op->ors_attrs = NULL; op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val ); @@ -1350,8 +1383,8 @@ syncrepl_del_nonpresent( op->o_nocaching = 1; op->o_managedsait = 0; - if ( limits_check( op, &rs ) == 0 ) { - be->be_search( op, &rs ); + if ( limits_check( op, &rs_search ) == 0 ) { + rc = be->be_search( op, &rs_search ); } op->o_managedsait = 1; @@ -1371,9 +1404,9 @@ syncrepl_del_nonpresent( cb.sc_private = si; op->o_req_dn = *np_prev->npe_name; op->o_req_ndn = *np_prev->npe_nname; - rc = op->o_bd->be_delete( op, &rs ); + rc = op->o_bd->be_delete( op, &rs_delete ); - if ( rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) { + if ( rs_delete.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF ) { mod = (Modifications *) ch_calloc( 1, sizeof( Modifications )); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = slap_schema.si_ad_objectClass; @@ -1393,7 +1426,7 @@ syncrepl_del_nonpresent( op->o_tag = LDAP_REQ_MODIFY; op->orm_modlist = modlist; - rc = be->be_modify( op, &rs ); + rc = be->be_modify( op, &rs_modify ); for ( ml = modlist; ml != NULL; ml = mlnext ) { mlnext = ml->sml_next; @@ -1410,7 +1443,7 @@ syncrepl_del_nonpresent( op->o_ndn = op->o_bd->be_rootndn; op->o_managedsait = 1; - while ( rs.sr_err == LDAP_SUCCESS && + while ( rs_delete.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) { op->o_delete_glue_parent = 0; if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) { @@ -1421,7 +1454,7 @@ syncrepl_del_nonpresent( op->o_req_ndn = pdn; op->o_callback = &cb; /* give it a root privil ? */ - op->o_bd->be_delete( op, &rs ); + op->o_bd->be_delete( op, &rs_delete ); } else { break; } @@ -1461,7 +1494,7 @@ syncrepl_add_glue( struct berval dn = {0, NULL}; struct berval ndn = {0, NULL}; Entry *glue; - SlapReply rs = {REP_RESULT}; + SlapReply rs_add = {REP_RESULT}; char *ptr, *comma; op->o_tag = LDAP_REQ_ADD; @@ -1537,8 +1570,8 @@ syncrepl_add_glue( op->o_req_dn = glue->e_name; op->o_req_ndn = glue->e_nname; op->ora_e = glue; - rc = be->be_add ( op, &rs ); - if ( rc == LDAP_SUCCESS ) { + rc = be->be_add ( op, &rs_add ); + if ( rs_add.sr_err == LDAP_SUCCESS ) { be_entry_release_w( op, glue ); } else { /* incl. ALREADY EXIST */ @@ -1565,8 +1598,8 @@ syncrepl_add_glue( op->o_req_dn = e->e_name; op->o_req_ndn = e->e_nname; op->ora_e = e; - rc = be->be_add ( op, &rs ); - if ( rc == LDAP_SUCCESS ) { + rc = be->be_add ( op, &rs_add ); + if ( rs_add.sr_err == LDAP_SUCCESS ) { be_entry_release_w( op, e ); } else { entry_free( e ); @@ -1624,7 +1657,8 @@ syncrepl_updateCookie( struct berval slap_syncrepl_cn_bv = BER_BVNULL; slap_callback cb = { NULL }; - SlapReply rs = {REP_RESULT}; + SlapReply rs_add = {REP_RESULT}; + SlapReply rs_modify = {REP_RESULT}; slap_sync_cookie_free( &si->si_syncCookie, 0 ); slap_dup_sync_cookie( &si->si_syncCookie, syncCookie ); @@ -1730,19 +1764,19 @@ syncrepl_updateCookie( update_cookie_retry: op->o_tag = LDAP_REQ_MODIFY; op->orm_modlist = modlist; - rc = be->be_modify( op, &rs ); + rc = be->be_modify( op, &rs_modify ); - if ( rc != LDAP_SUCCESS ) { - if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT ) { + if ( rs_modify.sr_err != LDAP_SUCCESS ) { + if ( rs_modify.sr_err == LDAP_REFERRAL || + rs_modify.sr_err == LDAP_NO_SUCH_OBJECT ) { op->o_tag = LDAP_REQ_ADD; op->ora_e = e; - rc = be->be_add( op, &rs ); - if ( rc != LDAP_SUCCESS ) { - if ( rc == LDAP_ALREADY_EXISTS ) { + rc = be->be_add( op, &rs_add ); + if ( rs_add.sr_err != LDAP_SUCCESS ) { + if ( rs_add.sr_err == LDAP_ALREADY_EXISTS ) { goto update_cookie_retry; - } else if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT ) { + } else if ( rs_add.sr_err == LDAP_REFERRAL || + rs_add.sr_err == LDAP_NO_SUCH_OBJECT ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "cookie will be non-persistent\n", @@ -1755,12 +1789,10 @@ update_cookie_retry: } else { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "be_add failed (%d)\n", - rc, 0, 0 ); + "be_add failed (%d)\n", rs_add.sr_err, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "be_add failed (%d)\n", - rc, 0, 0 ); + "be_add failed (%d)\n", rs_add.sr_err, 0, 0 ); #endif } } else { @@ -1770,10 +1802,10 @@ update_cookie_retry: } else { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "be_modify failed (%d)\n", rc, 0, 0 ); + "be_modify failed (%d)\n", rs_modify.sr_err, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "be_modify failed (%d)\n", rc, 0, 0 ); + "be_modify failed (%d)\n", rs_modify.sr_err, 0, 0 ); #endif } } @@ -1843,14 +1875,24 @@ dn_callback( if ( si->si_syncUUID_ndn.bv_val != NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "dn_callback : multiple entries match dn\n", 0, 0, 0 ); + "dn_callback : consistency error - entryUUID is not unique\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "dn_callback : multiple entries match dn\n", 0, 0, 0 ); + "dn_callback : consistency error - entryUUID is not unique\n", 0, 0, 0 ); #endif } else { ber_dupbv_x( &si->si_syncUUID_ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx ); } + } else if ( rs->sr_type == REP_RESULT ) { + if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, + "dn_callback : consistency error - entryUUID is not unique\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, + "dn_callback : consistency error - entryUUID is not unique\n", 0, 0, 0 ); +#endif + } } return LDAP_SUCCESS; diff --git a/servers/slapd/value.c b/servers/slapd/value.c index 893803def9..3a71d10514 100644 --- a/servers/slapd/value.c +++ b/servers/slapd/value.c @@ -215,8 +215,6 @@ value_match( const char ** text ) { int rc; - struct berval nv1 = BER_BVNULL; - struct berval nv2 = BER_BVNULL; assert( mr != NULL ); @@ -225,13 +223,8 @@ value_match( } rc = (mr->smr_match)( match, flags, - ad->ad_type->sat_syntax, - mr, - nv1.bv_val != NULL ? &nv1 : v1, - nv2.bv_val != NULL ? &nv2 : v2 ); + ad->ad_type->sat_syntax, mr, v1, v2 ); - if (nv1.bv_val ) free( nv1.bv_val ); - if (nv2.bv_val ) free( nv2.bv_val ); return rc; } -- 2.39.5