X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=c8dc5281e80b06d045477b9078c9eaec7d0274af;hb=581c1ff6c74f5eb281b5e0052b2a5ca84a7679bd;hp=8209e2d91cbe17e1551ff7538f02ed0111a2f7ed;hpb=ed0bed72b9b4b52c1f4949fc84062a2bc214d0a4;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 8209e2d91c..c8dc5281e8 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2005 The OpenLDAP Foundation. + * Copyright 2003-2006 The OpenLDAP Foundation. * Portions Copyright 2003 by IBM Corporation. * Portions Copyright 2003 by Howard Chu, Symas Corporation. * All rights reserved. @@ -44,6 +44,11 @@ struct nonpresent_entry { #define SYNCLOG_LOGGING 0 /* doing a log-based update */ #define SYNCLOG_FALLBACK 1 /* doing a full refresh */ +#define RETRYNUM_FOREVER (-1) /* retry forever */ +#define RETRYNUM_TAIL (-2) /* end of retrynum array */ +#define RETRYNUM_VALID(n) ((n) >= RETRYNUM_FOREVER) /* valid retrynum */ +#define RETRYNUM_FINITE(n) ((n) > RETRYNUM_FOREVER) /* not forever */ + typedef struct syncinfo_s { struct slap_backend_db *si_be; struct re_s *si_re; @@ -97,7 +102,7 @@ static int syncrepl_entry( Modifications**,int, struct berval*, struct sync_cookie *, struct berval * ); -static void syncrepl_updateCookie( +static int syncrepl_updateCookie( syncinfo_t *, Operation *, struct berval *, struct sync_cookie * ); static struct berval * slap_uuidstr_from_normalized( @@ -625,8 +630,6 @@ do_syncrep2( int rc, err, i; ber_len_t len; - int rc_efree = 1; - struct berval *psub; Modifications *modlist = NULL; @@ -710,30 +713,28 @@ do_syncrep2( slap_parse_sync_cookie( &syncCookie, NULL ); } } + rc = 0; if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) { - entry = NULL; modlist = NULL; - if ( syncrepl_message_to_op( si, op, msg ) == LDAP_SUCCESS && + if (( rc = syncrepl_message_to_op( si, op, msg )) == LDAP_SUCCESS && !BER_BVISNULL( &syncCookie.ctxcsn ) ) { - syncrepl_updateCookie( si, op, psub, &syncCookie ); + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); } - } else if ( syncrepl_message_to_entry( si, op, msg, - &modlist, &entry, syncstate ) == LDAP_SUCCESS ) { - rc_efree = syncrepl_entry( si, op, entry, &modlist, - syncstate, &syncUUID, &syncCookie_req, &syncCookie.ctxcsn ); - if ( !BER_BVISNULL( &syncCookie.ctxcsn ) ) - { - syncrepl_updateCookie( si, op, psub, &syncCookie ); + } else if (( rc = syncrepl_message_to_entry( si, op, msg, + &modlist, &entry, syncstate )) == LDAP_SUCCESS ) { + if (( rc = syncrepl_entry( si, op, entry, &modlist, + syncstate, &syncUUID, &syncCookie_req, + &syncCookie.ctxcsn )) == LDAP_SUCCESS && + !BER_BVISNULL( &syncCookie.ctxcsn ) ) { + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); } } ldap_controls_free( rctrls ); if ( modlist ) { slap_mods_free( modlist, 1 ); } - if ( rc_efree && entry ) { - entry_free( entry ); - } - entry = NULL; + if ( rc ) + goto done; break; case LDAP_RES_SEARCH_REFERENCE: @@ -795,7 +796,7 @@ do_syncrep2( if ( !BER_BVISNULL( &syncCookie.ctxcsn ) && match < 0 && err == LDAP_SUCCESS ) { - syncrepl_updateCookie( si, op, psub, &syncCookie ); + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); } if ( rctrls ) { ldap_controls_free( rctrls ); @@ -938,7 +939,7 @@ do_syncrep2( if ( !BER_BVISNULL( &syncCookie.ctxcsn ) && match < 0 ) { - syncrepl_updateCookie( si, op, psub, &syncCookie); + rc = syncrepl_updateCookie( si, op, psub, &syncCookie); } if ( si->si_refreshPresent == 1 ) { @@ -1126,20 +1127,20 @@ reload: rtask->interval.tv_sec = si->si_interval; ldap_pvt_runqueue_resched( &slapd_rq, rtask, defer ); if ( si->si_retrynum ) { - for ( i = 0; si->si_retrynum_init[i] != -2; i++ ) { + for ( i = 0; si->si_retrynum_init[i] != RETRYNUM_TAIL; i++ ) { si->si_retrynum[i] = si->si_retrynum_init[i]; } - si->si_retrynum[i] = -2; + si->si_retrynum[i] = RETRYNUM_TAIL; } } else { for ( i = 0; si->si_retrynum && si->si_retrynum[i] <= 0; i++ ) { - if ( si->si_retrynum[i] == -1 || si->si_retrynum[i] == -2 ) + if ( si->si_retrynum[i] == RETRYNUM_FOREVER || si->si_retrynum[i] == RETRYNUM_TAIL ) break; } - if ( !si->si_retrynum || si->si_retrynum[i] == -2 ) { + if ( !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) { ldap_pvt_runqueue_remove( &slapd_rq, rtask ); - } else if ( si->si_retrynum[i] >= -1 ) { + } else if ( RETRYNUM_VALID( si->si_retrynum[i] ) ) { if ( si->si_retrynum[i] > 0 ) si->si_retrynum[i]--; rtask->interval.tv_sec = si->si_retryinterval[i]; @@ -1358,11 +1359,17 @@ syncrepl_message_to_op( text, 0, 0 ); } else { rc = op->o_bd->be_add( op, &rs ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_message_to_op: be_add %s (%d)\n", + op->o_req_dn.bv_val, rc, 0 ); } be_entry_release_w( op, op->ora_e ); } else { op->orm_modlist = modlist; rc = op->o_bd->be_modify( op, &rs ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_message_to_op: be_modify %s (%d)\n", + op->o_req_dn.bv_val, rc, 0 ); } break; case LDAP_REQ_MODRDN: @@ -1381,10 +1388,20 @@ syncrepl_message_to_op( op->orr_newrdn = prdn; op->orr_nnewrdn = nrdn; op->orr_deleteoldrdn = deleteOldRdn; + op->orr_modlist = NULL; + if ( slap_modrdn2mods( op, &rs )) + goto done; rc = op->o_bd->be_modrdn( op, &rs ); + slap_mods_free( op->orr_modlist, 1 ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_message_to_op: be_modrdn %s (%d)\n", + op->o_req_dn.bv_val, rc, 0 ); break; case LDAP_REQ_DELETE: rc = op->o_bd->be_delete( op, &rs ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_message_to_op: be_delete %s (%d)\n", + op->o_req_dn.bv_val, rc, 0 ); break; } done: @@ -1463,7 +1480,6 @@ syncrepl_message_to_entry( } e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) ); - *entry = e; e->e_name = op->o_req_dn; e->e_nname = op->o_req_ndn; @@ -1539,9 +1555,10 @@ done: if ( rc != LDAP_SUCCESS ) { if ( e ) { entry_free( e ); - *entry = e = NULL; + e = NULL; } } + *entry = e; return rc; } @@ -1604,7 +1621,6 @@ syncrepl_entry( AttributeAssertion ava = { NULL, BER_BVNULL }; #endif int rc = LDAP_SUCCESS; - int ret = LDAP_SUCCESS; struct berval pdn = BER_BVNULL; dninfo dni = {0}; @@ -1660,12 +1676,12 @@ syncrepl_entry( ava.aa_value = *syncUUID; op->ors_filter = &f; - op->ors_filterstr.bv_len = STRLENOF( "(entryUUID=)" ) + syncUUID->bv_len; + op->ors_filterstr.bv_len = STRLENOF( "(entryUUID=)" ) + syncUUID_strrep.bv_len; op->ors_filterstr.bv_val = (char *) slap_sl_malloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); AC_MEMCPY( op->ors_filterstr.bv_val, "(entryUUID=", STRLENOF( "(entryUUID=" ) ); AC_MEMCPY( &op->ors_filterstr.bv_val[STRLENOF( "(entryUUID=" )], - syncUUID->bv_val, syncUUID->bv_len ); + syncUUID_strrep.bv_val, syncUUID_strrep.bv_len ); op->ors_filterstr.bv_val[op->ors_filterstr.bv_len - 1] = ')'; op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0'; @@ -1738,8 +1754,15 @@ syncrepl_entry( case LDAP_SYNC_MODIFY: { Attribute *a = attr_find( entry->e_attrs, slap_schema.si_ad_entryCSN ); - if ( a ) + if ( a ) { + /* FIXME: op->o_csn is assumed to be + * on the thread's slab; this needs + * to be cleared ASAP. + * What happens if already present? + */ + assert( BER_BVISNULL( &op->o_csn ) ); op->o_csn = a->a_vals[0]; + } } retry_add:; if ( BER_BVISNULL( &dni.dn )) { @@ -1756,15 +1779,15 @@ retry_add:; switch ( rs_add.sr_err ) { case LDAP_SUCCESS: be_entry_release_w( op, entry ); - ret = 0; + entry = NULL; break; case LDAP_REFERRAL: /* we assume that LDAP_NO_SUCH_OBJECT is returned * only if the suffix entry is not present */ case LDAP_NO_SUCH_OBJECT: - syncrepl_add_glue( op, entry ); - ret = 0; + rc = syncrepl_add_glue( op, entry ); + entry = NULL; break; /* if an entry was added via syncrepl_add_glue(), @@ -1800,7 +1823,8 @@ retry_add:; cb2.sc_response = dn_callback; cb2.sc_private = &dni; - be->be_search( &op2, &rs2 ); + rc = be->be_search( &op2, &rs2 ); + if ( rc ) goto done; retry = 0; goto retry_add; @@ -1811,7 +1835,6 @@ retry_add:; Debug( LDAP_DEBUG_ANY, "syncrepl_entry : be_add failed (%d)\n", rs_add.sr_err, 0, 0 ); - ret = 1; break; } goto done; @@ -1828,13 +1851,18 @@ retry_add:; dnParent( &dni.ndn, &noldp ); dnParent( &entry->e_nname, &nnewp ); - if ( !dn_match( &noldp, &newp )) { + if ( !dn_match( &noldp, &nnewp )) { dnParent( &entry->e_name, &newp ); op->orr_newSup = &newp; op->orr_nnewSup = &nnewp; } op->orr_deleteoldrdn = 0; + op->orr_modlist = NULL; + if (( rc = slap_modrdn2mods( op, &rs_modify ))) { + goto done; + } rc = be->be_modrdn( op, &rs_modify ); + slap_mods_free( op->orr_modlist, 1 ); Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s (%d)\n", "be_modrdn", rc, 0 ); @@ -1842,7 +1870,6 @@ retry_add:; op->o_req_dn = entry->e_name; op->o_req_ndn = entry->e_nname; } else { - ret = 1; goto done; } } @@ -1908,7 +1935,6 @@ retry_add:; rs_modify.sr_err, 0, 0 ); } } - ret = 1; goto done; case LDAP_SYNC_DELETE : if ( !BER_BVISNULL( &dni.dn )) { @@ -1936,17 +1962,15 @@ retry_add:; } } } - ret = 0; goto done; default : Debug( LDAP_DEBUG_ANY, "syncrepl_entry : unknown syncstate\n", 0, 0, 0 ); - ret = 1; goto done; } -done : +done: if ( !BER_BVISNULL( &syncUUID_strrep ) ) { slap_sl_free( syncUUID_strrep.bv_val, op->o_tmpmemctx ); BER_BVZERO( &syncUUID_strrep ); @@ -1960,8 +1984,10 @@ done : if ( !BER_BVISNULL( &dni.dn ) ) { op->o_tmpfree( dni.dn.bv_val, op->o_tmpmemctx ); } + if ( entry ) + entry_free( entry ); BER_BVZERO( &op->o_csn ); - return ret; + return rc; } static struct berval gcbva[] = { @@ -2025,8 +2051,12 @@ syncrepl_del_nonpresent( for (i=0; uuids[i].bv_val; i++) { op->ors_slimit = 1; + slap_uuidstr_from_normalized( &uf.f_av_value, &uuids[i], + op->o_tmpmemctx ); + filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); uf.f_av_value = uuids[i]; rc = be->be_search( op, &rs_search ); + op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } si->si_refreshDelete ^= NP_DELETE_ONE; } else { @@ -2064,6 +2094,9 @@ syncrepl_del_nonpresent( op->o_req_dn = *np_prev->npe_name; op->o_req_ndn = *np_prev->npe_nname; rc = op->o_bd->be_delete( op, &rs_delete ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_del_nonpresent: be_delete %s (%d)\n", + op->o_req_dn.bv_val, rc, 0 ); if ( rs_delete.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF ) { Modifications mod1, mod2; @@ -2114,12 +2147,15 @@ syncrepl_del_nonpresent( } slap_graduate_commit_csn( op ); + + op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); + BER_BVZERO( &op->o_csn ); } return; } -void +int syncrepl_add_glue( Operation* op, Entry *e ) @@ -2229,6 +2265,10 @@ syncrepl_add_glue( } else { /* incl. ALREADY EXIST */ entry_free( glue ); + if ( rs_add.sr_err != LDAP_ALREADY_EXISTS ) { + entry_free( e ); + return rc; + } } /* Move to next child */ @@ -2259,10 +2299,10 @@ syncrepl_add_glue( entry_free( e ); } - return; + return rc; } -static void +static int syncrepl_updateCookie( syncinfo_t *si, Operation *op, @@ -2278,18 +2318,14 @@ syncrepl_updateCookie( slap_callback cb = { NULL }; SlapReply rs_modify = {REP_RESULT}; - slap_sync_cookie_free( &si->si_syncCookie, 0 ); - slap_dup_sync_cookie( &si->si_syncCookie, syncCookie ); - mod.sml_op = LDAP_MOD_REPLACE; mod.sml_desc = slap_schema.si_ad_contextCSN; mod.sml_type = mod.sml_desc->ad_cname; mod.sml_values = vals; - vals[0] = si->si_syncCookie.ctxcsn; - vals[1].bv_val = NULL; - vals[1].bv_len = 0; + vals[0] = syncCookie->ctxcsn; + BER_BVZERO( &vals[1] ); - slap_queue_csn( op, &si->si_syncCookie.ctxcsn ); + slap_queue_csn( op, &syncCookie->ctxcsn ); op->o_tag = LDAP_REQ_MODIFY; @@ -2308,14 +2344,20 @@ syncrepl_updateCookie( rc = be->be_modify( op, &rs_modify ); op->o_msgid = 0; - if ( rs_modify.sr_err != LDAP_SUCCESS ) { + if ( rs_modify.sr_err == LDAP_SUCCESS ) { + slap_sync_cookie_free( &si->si_syncCookie, 0 ); + slap_dup_sync_cookie( &si->si_syncCookie, syncCookie ); + } else { Debug( LDAP_DEBUG_ANY, "be_modify failed (%d)\n", rs_modify.sr_err, 0, 0 ); } slap_graduate_commit_csn( op ); - return; + op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); + BER_BVZERO( &op->o_csn ); + + return rc; } static int @@ -2558,6 +2600,24 @@ avl_ber_bvfree( void *v_bv ) void syncinfo_free( syncinfo_t *sie ) { + if ( sie->si_ld ) { + if ( sie->si_conn_setup ) { + ber_socket_t s; + ldap_get_option( sie->si_ld, LDAP_OPT_DESC, &s ); + connection_client_stop( s ); + sie->si_conn_setup = 0; + } + ldap_unbind_ext( sie->si_ld, NULL, NULL ); + } + + /* re-fetch it, in case it was already removed */ + sie->si_re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, sie ); + if ( sie->si_re ) { + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, sie->si_re ) ) + ldap_pvt_runqueue_stoptask( &slapd_rq, sie->si_re ); + ldap_pvt_runqueue_remove( &slapd_rq, sie->si_re ); + } + ldap_pvt_thread_mutex_destroy( &sie->si_mutex ); bindconf_free( &sie->si_bindconf ); @@ -2613,9 +2673,6 @@ syncinfo_free( syncinfo_t *sie ) if ( sie->si_presentlist ) { avl_free( sie->si_presentlist, avl_ber_bvfree ); } - if ( sie->si_ld ) { - ldap_unbind_ext( sie->si_ld, NULL, NULL ); - } while ( !LDAP_LIST_EMPTY( &sie->si_nonpresentlist )) { struct nonpresent_entry* npe; npe = LDAP_LIST_FIRST( &sie->si_nonpresentlist ); @@ -2685,6 +2742,7 @@ static struct { { BER_BVC("one"), LDAP_SCOPE_ONELEVEL }, { BER_BVC("onelevel"), LDAP_SCOPE_ONELEVEL }, /* OpenLDAP extension */ { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC("subord"), LDAP_SCOPE_SUBORDINATE }, { BER_BVC("subordinate"), LDAP_SCOPE_SUBORDINATE }, { BER_BVC("sub"), LDAP_SCOPE_SUBTREE }, { BER_BVC("subtree"), LDAP_SCOPE_SUBTREE }, /* OpenLDAP extension */ @@ -2817,8 +2875,8 @@ parse_syncrepl_line( Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); return -1; } - } else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR "=", - STRLENOF( ATTRSONLYSTR "=" ) ) ) + } else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR, + STRLENOF( ATTRSONLYSTR ) ) ) { si->si_attrsonly = 1; } else if ( !strncasecmp( c->argv[ i ], ATTRSSTR "=", @@ -3001,12 +3059,14 @@ parse_syncrepl_line( } si->si_retryinterval[j] = (time_t)t; if ( *retry_list[j*2+1] == '+' ) { - si->si_retrynum_init[j] = -1; - si->si_retrynum[j] = -1; + si->si_retrynum_init[j] = RETRYNUM_FOREVER; + si->si_retrynum[j] = RETRYNUM_FOREVER; j++; break; } else { - if ( lutil_atoi( &si->si_retrynum_init[j], retry_list[j*2+1] ) != 0 ) { + if ( lutil_atoi( &si->si_retrynum_init[j], retry_list[j*2+1] ) != 0 + || si->si_retrynum_init[j] <= 0 ) + { snprintf( c->msg, sizeof( c->msg ), "Error: invalid initial retry number \"%s\" (#%d)", retry_list[j*2+1], j ); @@ -3014,7 +3074,9 @@ parse_syncrepl_line( /* do some cleanup */ return 1; } - if ( lutil_atoi( &si->si_retrynum[j], retry_list[j*2+1] ) != 0 ) { + if ( lutil_atoi( &si->si_retrynum[j], retry_list[j*2+1] ) != 0 + || si->si_retrynum[j] <= 0 ) + { snprintf( c->msg, sizeof( c->msg ), "Error: invalid retry number \"%s\" (#%d)", retry_list[j*2+1], j ); @@ -3024,8 +3086,8 @@ parse_syncrepl_line( } } } - si->si_retrynum_init[j] = -2; - si->si_retrynum[j] = -2; + si->si_retrynum_init[j] = RETRYNUM_TAIL; + si->si_retrynum[j] = RETRYNUM_TAIL; si->si_retryinterval[j] = 0; for ( k = 0; retry_list && retry_list[k]; k++ ) { @@ -3049,7 +3111,10 @@ parse_syncrepl_line( STRLENOF( SLIMITSTR "=") ) ) { val = c->argv[ i ] + STRLENOF( SLIMITSTR "=" ); - if ( lutil_atoi( &si->si_slimit, val ) != 0 ) { + if ( strcasecmp( val, "unlimited" ) == 0 ) { + si->si_slimit = 0; + + } else if ( lutil_atoi( &si->si_slimit, val ) != 0 || si->si_slimit < 0 ) { snprintf( c->msg, sizeof( c->msg ), "invalid size limit value \"%s\".\n", val ); @@ -3060,7 +3125,10 @@ parse_syncrepl_line( STRLENOF( TLIMITSTR "=" ) ) ) { val = c->argv[ i ] + STRLENOF( TLIMITSTR "=" ); - if ( lutil_atoi( &si->si_tlimit, val ) != 0 ) { + if ( strcasecmp( val, "unlimited" ) == 0 ) { + si->si_tlimit = 0; + + } else if ( lutil_atoi( &si->si_tlimit, val ) != 0 || si->si_tlimit < 0 ) { snprintf( c->msg, sizeof( c->msg ), "invalid time limit value \"%s\".\n", val ); @@ -3172,6 +3240,10 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv ) char buf[BUFSIZ*2], *ptr; int i; +#define WHATSLEFT ( sizeof( buf ) - ( ptr - buf ) ) + + BER_BVZERO( bv ); + /* temporarily inhibit bindconf from printing URI */ uri = si->si_bindconf.sb_uri; BER_BVZERO( &si->si_bindconf.sb_uri ); @@ -3179,68 +3251,91 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv ) si->si_bindconf.sb_uri = uri; ptr = buf; - ptr += snprintf( ptr, sizeof( buf ), IDSTR "=%03ld " PROVIDERSTR "=%s", + ptr += snprintf( ptr, WHATSLEFT, IDSTR "=%03ld " PROVIDERSTR "=%s", si->si_rid, si->si_bindconf.sb_uri.bv_val ); + if ( ptr - buf >= sizeof( buf ) ) return; if ( !BER_BVISNULL( &bc )) { + if ( WHATSLEFT <= bc.bv_len ) { + free( bc.bv_val ); + return; + } ptr = lutil_strcopy( ptr, bc.bv_val ); free( bc.bv_val ); } if ( !BER_BVISEMPTY( &si->si_filterstr )) { + if ( WHATSLEFT <= STRLENOF( " " FILTERSTR "=\"" "\"" ) + si->si_filterstr.bv_len ) return; ptr = lutil_strcopy( ptr, " " FILTERSTR "=\"" ); ptr = lutil_strcopy( ptr, si->si_filterstr.bv_val ); *ptr++ = '"'; } if ( !BER_BVISNULL( &si->si_base )) { + if ( WHATSLEFT <= STRLENOF( " " SEARCHBASESTR "=\"" "\"" ) + si->si_base.bv_len ) return; ptr = lutil_strcopy( ptr, " " SEARCHBASESTR "=\"" ); ptr = lutil_strcopy( ptr, si->si_base.bv_val ); *ptr++ = '"'; } if ( !BER_BVISEMPTY( &si->si_logfilterstr )) { + if ( WHATSLEFT <= STRLENOF( " " LOGFILTERSTR "=\"" "\"" ) + si->si_logfilterstr.bv_len ) return; ptr = lutil_strcopy( ptr, " " LOGFILTERSTR "=\"" ); ptr = lutil_strcopy( ptr, si->si_logfilterstr.bv_val ); *ptr++ = '"'; } if ( !BER_BVISNULL( &si->si_logbase )) { + if ( WHATSLEFT <= STRLENOF( " " LOGBASESTR "=\"" "\"" ) + si->si_logbase.bv_len ) return; ptr = lutil_strcopy( ptr, " " LOGBASESTR "=\"" ); ptr = lutil_strcopy( ptr, si->si_logbase.bv_val ); *ptr++ = '"'; } for (i=0; !BER_BVISNULL(&scopes[i].key);i++) { if ( si->si_scope == scopes[i].val ) { + if ( WHATSLEFT <= STRLENOF( " " SCOPESTR "=" ) + scopes[i].key.bv_len ) return; ptr = lutil_strcopy( ptr, " " SCOPESTR "=" ); ptr = lutil_strcopy( ptr, scopes[i].key.bv_val ); break; } } if ( si->si_attrsonly ) { - ptr = lutil_strcopy( ptr, " " ATTRSONLYSTR "=yes" ); + if ( WHATSLEFT <= STRLENOF( " " ATTRSONLYSTR "=\"" "\"" ) ) return; + ptr = lutil_strcopy( ptr, " " ATTRSONLYSTR ); } if ( si->si_anfile ) { - ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:" ); + if ( WHATSLEFT <= STRLENOF( " " ATTRSSTR "=\":include:" "\"" ) + strlen( si->si_anfile ) ) return; + ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:\"" ); ptr = lutil_strcopy( ptr, si->si_anfile ); + *ptr++ = '"'; } else if ( si->si_allattrs || si->si_allopattrs || - ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) { + ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) + { char *old; + + if ( WHATSLEFT <= STRLENOF( " " ATTRSONLYSTR "=\"" "\"" ) ) return; ptr = lutil_strcopy( ptr, " " ATTRSSTR "=\"" ); old = ptr; - ptr = anlist_unparse( si->si_anlist, ptr ); + /* FIXME: add check for overflow */ + ptr = anlist_unparse( si->si_anlist, ptr, WHATSLEFT ); if ( si->si_allattrs ) { + if ( WHATSLEFT <= STRLENOF( ",*\"" ) ) return; if ( old != ptr ) *ptr++ = ','; *ptr++ = '*'; } if ( si->si_allopattrs ) { + if ( WHATSLEFT <= STRLENOF( ",+\"" ) ) return; if ( old != ptr ) *ptr++ = ','; *ptr++ = '+'; } *ptr++ = '"'; } if ( si->si_exanlist && !BER_BVISNULL(&si->si_exanlist[0].an_name) ) { + if ( WHATSLEFT <= STRLENOF( " " EXATTRSSTR "=" ) ) return; ptr = lutil_strcopy( ptr, " " EXATTRSSTR "=" ); - ptr = anlist_unparse( si->si_exanlist, ptr ); + /* FIXME: add check for overflow */ + ptr = anlist_unparse( si->si_exanlist, ptr, WHATSLEFT ); } + if ( WHATSLEFT <= STRLENOF( " " SCHEMASTR "=" ) + STRLENOF( "off" ) ) return; ptr = lutil_strcopy( ptr, " " SCHEMASTR "=" ); ptr = lutil_strcopy( ptr, si->si_schemachecking ? "on" : "off" ); + if ( WHATSLEFT <= STRLENOF( " " TYPESTR "=" ) + STRLENOF( "refreshAndPersist" ) ) return; ptr = lutil_strcopy( ptr, " " TYPESTR "=" ); ptr = lutil_strcopy( ptr, si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ? "refreshAndPersist" : "refreshOnly" ); @@ -3256,34 +3351,40 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv ) hh = dd % 24; dd /= 24; ptr = lutil_strcopy( ptr, " " INTERVALSTR "=" ); - ptr += sprintf( ptr, "%02d:%02d:%02d:%02d", dd, hh, mm, ss ); + ptr += snprintf( ptr, WHATSLEFT, "%02d:%02d:%02d:%02d", dd, hh, mm, ss ); + if ( ptr - buf >= sizeof( buf ) ) return; } else if ( si->si_retryinterval ) { int space=0; + if ( WHATSLEFT <= STRLENOF( " " RETRYSTR "=\"" "\"" ) ) return; ptr = lutil_strcopy( ptr, " " RETRYSTR "=\"" ); for (i=0; si->si_retryinterval[i]; i++) { if ( space ) *ptr++ = ' '; space = 1; - ptr += sprintf( ptr, "%ld ", (long) si->si_retryinterval[i] ); - if ( si->si_retrynum_init[i] == -1 ) + ptr += snprintf( ptr, WHATSLEFT, "%ld ", (long) si->si_retryinterval[i] ); + if ( si->si_retrynum_init[i] == RETRYNUM_FOREVER ) *ptr++ = '+'; else - ptr += sprintf( ptr, "%d", si->si_retrynum_init[i] ); + ptr += snprintf( ptr, WHATSLEFT, "%d", si->si_retrynum_init[i] ); } + if ( WHATSLEFT <= STRLENOF( "\"" ) ) return; *ptr++ = '"'; } if ( si->si_slimit ) { + if ( WHATSLEFT <= STRLENOF( " " SLIMITSTR "=" ) ) return; ptr = lutil_strcopy( ptr, " " SLIMITSTR "=" ); - ptr += sprintf( ptr, "%d", si->si_slimit ); + ptr += snprintf( ptr, WHATSLEFT, "%d", si->si_slimit ); } if ( si->si_tlimit ) { + if ( WHATSLEFT <= STRLENOF( " " TLIMITSTR "=" ) ) return; ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" ); - ptr += sprintf( ptr, "%d", si->si_tlimit ); + ptr += snprintf( ptr, WHATSLEFT, "%d", si->si_tlimit ); } if ( si->si_syncdata ) { if ( enum_to_verb( datamodes, si->si_syncdata, &bc ) >= 0 ) { + if ( WHATSLEFT <= STRLENOF( " " SYNCDATASTR "=" ) + bc.bv_len ) return; ptr = lutil_strcopy( ptr, " " SYNCDATASTR "=" ); ptr = lutil_strcopy( ptr, bc.bv_val ); } @@ -3308,12 +3409,6 @@ syncrepl_config( ConfigArgs *c ) struct re_s *re; if ( c->be->be_syncinfo ) { - re = c->be->be_syncinfo->si_re; - if ( re ) { - if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) ) - ldap_pvt_runqueue_stoptask( &slapd_rq, re ); - ldap_pvt_runqueue_remove( &slapd_rq, re ); - } syncinfo_free( c->be->be_syncinfo ); c->be->be_syncinfo = NULL; }