#endif
#include <lutil.h>
-#include <ldap_rq.h>
#include "config.h"
static Avlnode *CfOcTree;
-static int add_syncrepl LDAP_P(( Backend *, char **, int ));
-static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
-static void syncrepl_unparse LDAP_P (( syncinfo_t *, struct berval *));
static int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs,
int *renumber );
static ConfigDriver config_security;
static ConfigDriver config_referral;
static ConfigDriver config_loglevel;
-static ConfigDriver config_syncrepl;
static ConfigDriver config_replica;
static ConfigDriver config_updatedn;
static ConfigDriver config_updateref;
static ConfigDriver config_tls_option;
static ConfigDriver config_tls_config;
#endif
+extern ConfigDriver syncrepl_config;
enum {
CFG_ACL = 1,
&config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
"SYNTAX OMsDN )", NULL, NULL },
{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
- &config_syncrepl, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
+ &syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_THREADS,
&config_generic, "( OLcfgGlAt:66 NAME 'olcThreads' "
return(0);
}
-static int
-config_syncrepl(ConfigArgs *c) {
- if (c->op == SLAP_CONFIG_EMIT) {
- if ( c->be->be_syncinfo ) {
- struct berval bv;
- syncrepl_unparse( c->be->be_syncinfo, &bv );
- ber_bvarray_add( &c->rvalue_vals, &bv );
- return 0;
- }
- return 1;
- } else if ( c->op == LDAP_MOD_DELETE ) {
- struct re_s *re;
-
- if ( c->be->be_syncinfo ) {
- re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, c->be->be_syncinfo );
- 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;
- }
- return 0;
- }
- if(SLAP_SHADOW(c->be)) {
- Debug(LDAP_DEBUG_ANY, "%s: "
- "syncrepl: database already shadowed.\n",
- c->log, 0, 0);
- return(1);
- } else if(add_syncrepl(c->be, c->argv, c->argc)) {
- return(1);
- }
- SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SYNC_SHADOW);
- return(0);
-}
-
static int
config_referral(ConfigArgs *c) {
struct berval val;
return(0);
}
-static char *
+char *
anlist_unparse( AttributeName *an, char *ptr ) {
int comma = 0;
}
#endif
-static int
-add_syncrepl(
- Backend *be,
- char **cargv,
- int cargc
-)
-{
- syncinfo_t *si;
- int rc = 0;
-
- if ( !( be->be_search && be->be_add && be->be_modify && be->be_delete )) {
- Debug( LDAP_DEBUG_ANY, "database %s does not support operations "
- "required for syncrepl\n", be->be_type, 0, 0 );
- return 1;
- }
- si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
-
- if ( si == NULL ) {
- Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
- return 1;
- }
-
- si->si_bindconf.sb_tls = SB_TLS_OFF;
- si->si_bindconf.sb_method = LDAP_AUTH_SIMPLE;
- si->si_schemachecking = 0;
- ber_str2bv( "(objectclass=*)", STRLENOF("(objectclass=*)"), 1,
- &si->si_filterstr );
- si->si_base.bv_val = NULL;
- si->si_scope = LDAP_SCOPE_SUBTREE;
- si->si_attrsonly = 0;
- si->si_anlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
- si->si_exanlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
- si->si_attrs = NULL;
- si->si_allattrs = 0;
- si->si_allopattrs = 0;
- si->si_exattrs = NULL;
- si->si_type = LDAP_SYNC_REFRESH_ONLY;
- si->si_interval = 86400;
- si->si_retryinterval = NULL;
- si->si_retrynum_init = NULL;
- si->si_retrynum = NULL;
- si->si_manageDSAit = 0;
- si->si_tlimit = 0;
- si->si_slimit = 0;
-
- si->si_presentlist = NULL;
- LDAP_LIST_INIT( &si->si_nonpresentlist );
- ldap_pvt_thread_mutex_init( &si->si_mutex );
-
- rc = parse_syncrepl_line( cargv, cargc, si );
-
- if ( rc < 0 ) {
- Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
- syncinfo_free( si );
- return 1;
- } else {
- Debug( LDAP_DEBUG_CONFIG,
- "Config: ** successfully added syncrepl \"%s\"\n",
- BER_BVISNULL( &si->si_provideruri ) ?
- "(null)" : si->si_provideruri.bv_val, 0, 0 );
- if ( !si->si_schemachecking ) {
- SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
- }
- si->si_be = be;
- be->be_syncinfo = si;
- init_syncrepl( si );
- ldap_pvt_runqueue_insert( &slapd_rq,si->si_interval,do_syncrepl,si );
- return 0;
- }
-}
-
-/* NOTE: used & documented in slapd.conf(5) */
-#define IDSTR "rid"
-#define PROVIDERSTR "provider"
-#define TYPESTR "type"
-#define INTERVALSTR "interval"
-#define SEARCHBASESTR "searchbase"
-#define FILTERSTR "filter"
-#define SCOPESTR "scope"
-#define ATTRSSTR "attrs"
-#define ATTRSONLYSTR "attrsonly"
-#define SLIMITSTR "sizelimit"
-#define TLIMITSTR "timelimit"
-#define SCHEMASTR "schemachecking"
-
-/* FIXME: undocumented */
-#define OLDAUTHCSTR "bindprincipal"
-#define EXATTRSSTR "exattrs"
-#define RETRYSTR "retry"
-
-/* FIXME: unused */
-#define LASTMODSTR "lastmod"
-#define LMGENSTR "gen"
-#define LMNOSTR "no"
-#define LMREQSTR "req"
-#define SRVTABSTR "srvtab"
-#define SUFFIXSTR "suffix"
-#define MANAGEDSAITSTR "manageDSAit"
-
-/* mandatory */
-#define GOT_ID 0x0001
-#define GOT_PROVIDER 0x0002
-
-/* check */
-#define GOT_ALL (GOT_ID|GOT_PROVIDER)
-
-static struct {
- struct berval key;
- int val;
-} scopes[] = {
- { BER_BVC("base"), LDAP_SCOPE_BASE },
- { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
-#ifdef LDAP_SCOPE_SUBORDINATE
- { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
- { BER_BVC("subordinate"), 0 },
-#endif
- { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
- { BER_BVNULL, 0 }
-};
-
-static int
-parse_syncrepl_line(
- char **cargv,
- int cargc,
- syncinfo_t *si
-)
-{
- int gots = 0;
- int i;
- char *val;
-
- for ( i = 1; i < cargc; i++ ) {
- if ( !strncasecmp( cargv[ i ], IDSTR "=",
- STRLENOF( IDSTR "=" ) ) )
- {
- int tmp;
- /* '\0' string terminator accounts for '=' */
- val = cargv[ i ] + STRLENOF( IDSTR "=" );
- tmp= atoi( val );
- if ( tmp >= 1000 || tmp < 0 ) {
- fprintf( stderr, "Error: parse_syncrepl_line: "
- "syncrepl id %d is out of range [0..999]\n", tmp );
- return -1;
- }
- si->si_rid = tmp;
- gots |= GOT_ID;
- } else if ( !strncasecmp( cargv[ i ], PROVIDERSTR "=",
- STRLENOF( PROVIDERSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( PROVIDERSTR "=" );
- ber_str2bv( val, 0, 1, &si->si_provideruri );
- gots |= GOT_PROVIDER;
- } else if ( !strncasecmp( cargv[ i ], SCHEMASTR "=",
- STRLENOF( SCHEMASTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( SCHEMASTR "=" );
- if ( !strncasecmp( val, "on", STRLENOF( "on" ) )) {
- si->si_schemachecking = 1;
- } else if ( !strncasecmp( val, "off", STRLENOF( "off" ) ) ) {
- si->si_schemachecking = 0;
- } else {
- si->si_schemachecking = 1;
- }
- } else if ( !strncasecmp( cargv[ i ], FILTERSTR "=",
- STRLENOF( FILTERSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
- ber_str2bv( val, 0, 1, &si->si_filterstr );
- } else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
- STRLENOF( SEARCHBASESTR "=" ) ) )
- {
- struct berval bv;
- int rc;
-
- val = cargv[ i ] + STRLENOF( SEARCHBASESTR "=" );
- if ( si->si_base.bv_val ) {
- ch_free( si->si_base.bv_val );
- }
- ber_str2bv( val, 0, 0, &bv );
- rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
- if ( rc != LDAP_SUCCESS ) {
- fprintf( stderr, "Invalid base DN \"%s\": %d (%s)\n",
- val, rc, ldap_err2string( rc ) );
- return -1;
- }
- } else if ( !strncasecmp( cargv[ i ], SCOPESTR "=",
- STRLENOF( SCOPESTR "=" ) ) )
- {
- int j;
- val = cargv[ i ] + STRLENOF( SCOPESTR "=" );
- for ( j=0; !BER_BVISNULL(&scopes[j].key); j++ ) {
- if (!strncasecmp( val, scopes[j].key.bv_val,
- scopes[j].key.bv_len )) {
- while (!scopes[j].val) j--;
- si->si_scope = scopes[j].val;
- break;
- }
- }
- if ( BER_BVISNULL(&scopes[j].key) ) {
- fprintf( stderr, "Error: parse_syncrepl_line: "
- "unknown scope \"%s\"\n", val);
- return -1;
- }
- } else if ( !strncasecmp( cargv[ i ], ATTRSONLYSTR "=",
- STRLENOF( ATTRSONLYSTR "=" ) ) )
- {
- si->si_attrsonly = 1;
- } else if ( !strncasecmp( cargv[ i ], ATTRSSTR "=",
- STRLENOF( ATTRSSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( ATTRSSTR "=" );
- if ( !strncasecmp( val, ":include:", STRLENOF(":include:") ) ) {
- char *attr_fname;
- attr_fname = ch_strdup( val + STRLENOF(":include:") );
- si->si_anlist = file2anlist( si->si_anlist, attr_fname, " ,\t" );
- if ( si->si_anlist == NULL ) {
- ch_free( attr_fname );
- return -1;
- }
- si->si_anfile = attr_fname;
- } else {
- char *str, *s, *next;
- char delimstr[] = " ,\t";
- str = ch_strdup( val );
- for ( s = ldap_pvt_strtok( str, delimstr, &next );
- s != NULL;
- s = ldap_pvt_strtok( NULL, delimstr, &next ) )
- {
- if ( strlen(s) == 1 && *s == '*' ) {
- si->si_allattrs = 1;
- *(val + ( s - str )) = delimstr[0];
- }
- if ( strlen(s) == 1 && *s == '+' ) {
- si->si_allopattrs = 1;
- *(val + ( s - str )) = delimstr[0];
- }
- }
- ch_free( str );
- si->si_anlist = str2anlist( si->si_anlist, val, " ,\t" );
- if ( si->si_anlist == NULL ) {
- return -1;
- }
- }
- } else if ( !strncasecmp( cargv[ i ], EXATTRSSTR "=",
- STRLENOF( EXATTRSSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( EXATTRSSTR "=" );
- if ( !strncasecmp( val, ":include:", STRLENOF(":include:") )) {
- char *attr_fname;
- attr_fname = ch_strdup( val + STRLENOF(":include:") );
- si->si_exanlist = file2anlist(
- si->si_exanlist, attr_fname, " ,\t" );
- if ( si->si_exanlist == NULL ) {
- ch_free( attr_fname );
- return -1;
- }
- ch_free( attr_fname );
- } else {
- si->si_exanlist = str2anlist( si->si_exanlist, val, " ,\t" );
- if ( si->si_exanlist == NULL ) {
- return -1;
- }
- }
- } else if ( !strncasecmp( cargv[ i ], TYPESTR "=",
- STRLENOF( TYPESTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( TYPESTR "=" );
- if ( !strncasecmp( val, "refreshOnly",
- STRLENOF("refreshOnly") ))
- {
- si->si_type = LDAP_SYNC_REFRESH_ONLY;
- } else if ( !strncasecmp( val, "refreshAndPersist",
- STRLENOF("refreshAndPersist") ))
- {
- si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST;
- si->si_interval = 60;
- } else {
- fprintf( stderr, "Error: parse_syncrepl_line: "
- "unknown sync type \"%s\"\n", val);
- return -1;
- }
- } else if ( !strncasecmp( cargv[ i ], INTERVALSTR "=",
- STRLENOF( INTERVALSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( INTERVALSTR "=" );
- 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;
- }
- 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 "=",
- STRLENOF( RETRYSTR "=" ) ) )
- {
- char **retry_list;
- int j, k, n;
-
- val = cargv[ i ] + STRLENOF( RETRYSTR "=" );
- retry_list = (char **) ch_calloc( 1, sizeof( char * ));
- retry_list[0] = NULL;
-
- slap_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 "=",
- STRLENOF( MANAGEDSAITSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( MANAGEDSAITSTR "=" );
- si->si_manageDSAit = atoi( val );
- } else if ( !strncasecmp( cargv[ i ], SLIMITSTR "=",
- STRLENOF( SLIMITSTR "=") ) )
- {
- val = cargv[ i ] + STRLENOF( SLIMITSTR "=" );
- si->si_slimit = atoi( val );
- } else if ( !strncasecmp( cargv[ i ], TLIMITSTR "=",
- STRLENOF( TLIMITSTR "=" ) ) )
- {
- val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
- si->si_tlimit = atoi( val );
- } else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
- fprintf( stderr, "Error: parse_syncrepl_line: "
- "unknown keyword \"%s\"\n", cargv[ i ] );
- return -1;
- }
- }
-
- if ( gots != GOT_ALL ) {
- fprintf( stderr,
- "Error: Malformed \"syncrepl\" line in slapd config file" );
- return -1;
- }
-
- return 0;
-}
-
-static void
-syncrepl_unparse( syncinfo_t *si, struct berval *bv )
-{
- struct berval bc;
- char buf[BUFSIZ*2], *ptr;
- int i, len;
-
- bindconf_unparse( &si->si_bindconf, &bc );
- ptr = buf;
- ptr += sprintf( ptr, IDSTR "=%03d " PROVIDERSTR "=%s",
- si->si_rid, si->si_provideruri.bv_val );
- if ( !BER_BVISNULL( &bc )) {
- ptr = lutil_strcopy( ptr, bc.bv_val );
- free( bc.bv_val );
- }
- if ( !BER_BVISEMPTY( &si->si_filterstr )) {
- ptr = lutil_strcopy( ptr, " " FILTERSTR "=\"" );
- ptr = lutil_strcopy( ptr, si->si_filterstr.bv_val );
- *ptr++ = '"';
- }
- if ( !BER_BVISNULL( &si->si_base )) {
- ptr = lutil_strcopy( ptr, " " SEARCHBASESTR "=\"" );
- ptr = lutil_strcopy( ptr, si->si_base.bv_val );
- *ptr++ = '"';
- }
- for (i=0; !BER_BVISNULL(&scopes[i].key);i++) {
- if ( si->si_scope == scopes[i].val ) {
- 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 ( si->si_anfile ) {
- ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:" );
- ptr = lutil_strcopy( ptr, si->si_anfile );
- } else if ( si->si_allattrs || si->si_allopattrs ||
- ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) {
- char *old;
- ptr = lutil_strcopy( ptr, " " ATTRSSTR "=\"" );
- old = ptr;
- ptr = anlist_unparse( si->si_anlist, ptr );
- if ( si->si_allattrs ) {
- if ( old != ptr ) *ptr++ = ',';
- *ptr++ = '*';
- }
- if ( si->si_allopattrs ) {
- if ( old != ptr ) *ptr++ = ',';
- *ptr++ = '+';
- }
- *ptr++ = '"';
- }
- if ( si->si_exanlist && !BER_BVISNULL(&si->si_exanlist[0].an_name) ) {
- ptr = lutil_strcopy( ptr, " " EXATTRSSTR "=" );
- ptr = anlist_unparse( si->si_exanlist, ptr );
- }
- ptr = lutil_strcopy( ptr, " " SCHEMASTR "=" );
- ptr = lutil_strcopy( ptr, si->si_schemachecking ? "on" : "off" );
-
- ptr = lutil_strcopy( ptr, " " TYPESTR "=" );
- ptr = lutil_strcopy( ptr, si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ?
- "refreshAndPersist" : "refreshOnly" );
-
- if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
- int dd, hh, mm, ss;
-
- dd = si->si_interval;
- ss = dd % 60;
- dd /= 60;
- mm = dd % 60;
- dd /= 60;
- hh = dd % 24;
- dd /= 24;
- ptr = lutil_strcopy( ptr, " " INTERVALSTR "=" );
- ptr += sprintf( ptr, "%02d:%02d:%02d:%02d", dd, hh, mm, ss );
- } else if ( si->si_retryinterval ) {
- int space=0;
- ptr = lutil_strcopy( ptr, " " RETRYSTR "=\"" );
- for (i=0; si->si_retryinterval[i]; i++) {
- if ( space ) *ptr++ = ' ';
- space = 1;
- ptr += sprintf( ptr, "%d", si->si_retryinterval[i] );
- if ( si->si_retrynum_init[i] == -1 )
- *ptr++ = '+';
- else
- ptr += sprintf( ptr, "%d", si->si_retrynum_init );
- }
- *ptr++ = '"';
- }
-
-#if 0 /* FIXME: unused in syncrepl.c, should remove it */
- ptr = lutil_strcopy( ptr, " " MANAGEDSAITSTR "=" );
- ptr += sprintf( ptr, "%d", si->si_manageDSAit );
-#endif
-
- if ( si->si_slimit ) {
- ptr = lutil_strcopy( ptr, " " SLIMITSTR "=" );
- ptr += sprintf( ptr, "%d", si->si_slimit );
- }
-
- if ( si->si_tlimit ) {
- ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
- ptr += sprintf( ptr, "%d", si->si_tlimit );
- }
- bc.bv_len = ptr - buf;
- bc.bv_val = buf;
- ber_dupbv( bv, &bc );
-}
-
static CfEntryInfo *
config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
{
#define ARG_MAGIC 0x80000000
#define ARG_BAD_CONF 0xdead0000 /* overload return values */
-#define ARG_UNKNOWN 0xc0de0000
extern ConfigTable config_back_cf_table[];
char *def;
ConfigType cft;
ObjectClass **oc;
-#if 0
- BI_op_add *add; /* optional, add-specific processing */
- BI_op_delete *del; /* mandatory, delete implementation */
- BI_op_modify *mod; /* optional, mod-specific */
- BI_op_modrdn *ren; /* optional, modrdn... */
-#endif
} ConfigOCs;
struct config_args_s;
LDAP_SLAPD_F (void) bindconf_free LDAP_P(( slap_bindconf *bc ));
LDAP_SLAPD_F (int) config_generic_wrapper LDAP_P(( Backend *be,
const char *fname, int lineno, int argc, char **argv ));
+LDAP_SLAPD_F (char *) anlist_unparse LDAP_P(( AttributeName *, char * ));
#ifdef LDAP_SLAPI
LDAP_SLAPD_V (int) slapi_plugins_used;
* syncrepl.c
*/
-LDAP_SLAPD_F (void) init_syncrepl LDAP_P((syncinfo_t *));
-LDAP_SLAPD_F (void*) do_syncrepl LDAP_P((void *, void *));
-LDAP_SLAPD_F (int) syncrepl_message_to_entry LDAP_P((
- syncinfo_t *, Operation *, LDAPMessage *,
- Modifications **, Entry **, int ));
-LDAP_SLAPD_F (int) syncrepl_entry LDAP_P((
- syncinfo_t *, Operation*, Entry*,
- Modifications**,int, struct berval*,
- struct sync_cookie *,
- struct berval * ));
-LDAP_SLAPD_F (void) syncrepl_updateCookie LDAP_P((
- syncinfo_t *, Operation *, struct berval *,
- struct sync_cookie * ));
LDAP_SLAPD_F (void) syncrepl_add_glue LDAP_P((
Operation*, Entry* ));
-LDAP_SLAPD_F (Entry*) slap_create_syncrepl_entry LDAP_P((
- Backend *, struct berval *,
- struct berval *, struct berval * ));
-LDAP_SLAPD_F (struct berval *) slap_uuidstr_from_normalized LDAP_P((
- struct berval *, struct berval *, void * ));
-LDAP_SLAPD_F (void) syncinfo_free LDAP_P(( syncinfo_t * ));
+LDAP_SLAPD_F (void) syncinfo_free LDAP_P(( struct syncinfo_s * ));
/* syntax.c */
LDAP_SLAPD_F (Syntax *) syn_find LDAP_P((
* syncinfo structure for syncrepl
*/
+struct syncinfo_s;
+
#define SLAP_SYNC_RID_SIZE 3
#define SLAP_SYNCUUID_SET_SIZE 256
#define SLAP_SYNC_UPDATE_MSGID 2
-struct nonpresent_entry {
- struct berval *npe_name;
- struct berval *npe_nname;
- LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
-};
-
struct sync_cookie {
struct berval ctxcsn;
struct berval octet_str;
LDAP_STAILQ_HEAD( slap_sync_cookie_s, sync_cookie );
-typedef struct syncinfo_s {
- struct slap_backend_db *si_be;
- long si_rid;
- struct berval si_provideruri;
- slap_bindconf si_bindconf;
- struct berval si_filterstr;
- struct berval si_base;
- int si_scope;
- int si_attrsonly;
- char *si_anfile;
- AttributeName *si_anlist;
- AttributeName *si_exanlist;
- char **si_attrs;
- char **si_exattrs;
- int si_allattrs;
- int si_allopattrs;
- int si_schemachecking;
- 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;
- int si_tlimit;
- int si_refreshDelete;
- int si_refreshPresent;
- Avlnode *si_presentlist;
- LDAP *si_ld;
- LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
- ldap_pvt_thread_mutex_t si_mutex;
-} syncinfo_t;
-
LDAP_TAILQ_HEAD( be_pcl, slap_csn_entry );
#ifndef SLAP_MAX_CIDS
struct be_pcl *be_pending_csn_list;
ldap_pvt_thread_mutex_t be_pcl_mutex;
ldap_pvt_thread_mutex_t *be_pcl_mutexp;
- syncinfo_t *be_syncinfo; /* For syncrepl */
+ struct syncinfo_s *be_syncinfo; /* For syncrepl */
void *be_pb; /* Netscape plugin */
struct ConfigTable *be_cf_table;
#include "slap.h"
#include "lutil_ldap.h"
+#include "config.h"
+
#include "ldap_rq.h"
/* FIXME: for ldap_ld_free() */
#undef ldap_debug
#include "../../libraries/libldap/ldap-int.h"
+struct nonpresent_entry {
+ struct berval *npe_name;
+ struct berval *npe_nname;
+ LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
+};
+
+typedef struct syncinfo_s {
+ struct slap_backend_db *si_be;
+ long si_rid;
+ struct berval si_provideruri;
+ slap_bindconf si_bindconf;
+ struct berval si_filterstr;
+ struct berval si_base;
+ int si_scope;
+ int si_attrsonly;
+ char *si_anfile;
+ AttributeName *si_anlist;
+ AttributeName *si_exanlist;
+ char **si_attrs;
+ char **si_exattrs;
+ int si_allattrs;
+ int si_allopattrs;
+ int si_schemachecking;
+ 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;
+ int si_tlimit;
+ int si_refreshDelete;
+ int si_refreshPresent;
+ Avlnode *si_presentlist;
+ LDAP *si_ld;
+ LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
+ ldap_pvt_thread_mutex_t si_mutex;
+} syncinfo_t;
+
static int syncuuid_cmp( const void *, const void * );
static void avl_ber_bvfree( void * );
static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
+static int syncrepl_message_to_entry(
+ syncinfo_t *, Operation *, LDAPMessage *,
+ Modifications **, Entry **, int );
+static int syncrepl_entry(
+ syncinfo_t *, Operation*, Entry*,
+ Modifications**,int, struct berval*,
+ struct sync_cookie *,
+ struct berval * );
+static void syncrepl_updateCookie(
+ syncinfo_t *, Operation *, struct berval *,
+ struct sync_cookie * );
+static struct berval * slap_uuidstr_from_normalized(
+ struct berval *, struct berval *, void * );
/* callback functions */
static int dn_callback( struct slap_op *, struct slap_rep * );
static AttributeDescription *sync_descs[4];
-void
+static void
init_syncrepl(syncinfo_t *si)
{
int i, j, k, l, n;
}
ch_free( sie );
}
+
+
+
+/* NOTE: used & documented in slapd.conf(5) */
+#define IDSTR "rid"
+#define PROVIDERSTR "provider"
+#define TYPESTR "type"
+#define INTERVALSTR "interval"
+#define SEARCHBASESTR "searchbase"
+#define FILTERSTR "filter"
+#define SCOPESTR "scope"
+#define ATTRSSTR "attrs"
+#define ATTRSONLYSTR "attrsonly"
+#define SLIMITSTR "sizelimit"
+#define TLIMITSTR "timelimit"
+#define SCHEMASTR "schemachecking"
+
+/* FIXME: undocumented */
+#define OLDAUTHCSTR "bindprincipal"
+#define EXATTRSSTR "exattrs"
+#define RETRYSTR "retry"
+
+/* FIXME: unused */
+#define LASTMODSTR "lastmod"
+#define LMGENSTR "gen"
+#define LMNOSTR "no"
+#define LMREQSTR "req"
+#define SRVTABSTR "srvtab"
+#define SUFFIXSTR "suffix"
+#define MANAGEDSAITSTR "manageDSAit"
+
+/* mandatory */
+#define GOT_ID 0x0001
+#define GOT_PROVIDER 0x0002
+
+/* check */
+#define GOT_ALL (GOT_ID|GOT_PROVIDER)
+
+static struct {
+ struct berval key;
+ int val;
+} scopes[] = {
+ { BER_BVC("base"), LDAP_SCOPE_BASE },
+ { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
+#ifdef LDAP_SCOPE_SUBORDINATE
+ { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
+ { BER_BVC("subordinate"), 0 },
+#endif
+ { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
+ { BER_BVNULL, 0 }
+};
+
+static int
+parse_syncrepl_line(
+ char **cargv,
+ int cargc,
+ syncinfo_t *si
+)
+{
+ int gots = 0;
+ int i;
+ char *val;
+
+ for ( i = 1; i < cargc; i++ ) {
+ if ( !strncasecmp( cargv[ i ], IDSTR "=",
+ STRLENOF( IDSTR "=" ) ) )
+ {
+ int tmp;
+ /* '\0' string terminator accounts for '=' */
+ val = cargv[ i ] + STRLENOF( IDSTR "=" );
+ tmp= atoi( val );
+ if ( tmp >= 1000 || tmp < 0 ) {
+ fprintf( stderr, "Error: parse_syncrepl_line: "
+ "syncrepl id %d is out of range [0..999]\n", tmp );
+ return -1;
+ }
+ si->si_rid = tmp;
+ gots |= GOT_ID;
+ } else if ( !strncasecmp( cargv[ i ], PROVIDERSTR "=",
+ STRLENOF( PROVIDERSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( PROVIDERSTR "=" );
+ ber_str2bv( val, 0, 1, &si->si_provideruri );
+ gots |= GOT_PROVIDER;
+ } else if ( !strncasecmp( cargv[ i ], SCHEMASTR "=",
+ STRLENOF( SCHEMASTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( SCHEMASTR "=" );
+ if ( !strncasecmp( val, "on", STRLENOF( "on" ) )) {
+ si->si_schemachecking = 1;
+ } else if ( !strncasecmp( val, "off", STRLENOF( "off" ) ) ) {
+ si->si_schemachecking = 0;
+ } else {
+ si->si_schemachecking = 1;
+ }
+ } else if ( !strncasecmp( cargv[ i ], FILTERSTR "=",
+ STRLENOF( FILTERSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
+ ber_str2bv( val, 0, 1, &si->si_filterstr );
+ } else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
+ STRLENOF( SEARCHBASESTR "=" ) ) )
+ {
+ struct berval bv;
+ int rc;
+
+ val = cargv[ i ] + STRLENOF( SEARCHBASESTR "=" );
+ if ( si->si_base.bv_val ) {
+ ch_free( si->si_base.bv_val );
+ }
+ ber_str2bv( val, 0, 0, &bv );
+ rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ fprintf( stderr, "Invalid base DN \"%s\": %d (%s)\n",
+ val, rc, ldap_err2string( rc ) );
+ return -1;
+ }
+ } else if ( !strncasecmp( cargv[ i ], SCOPESTR "=",
+ STRLENOF( SCOPESTR "=" ) ) )
+ {
+ int j;
+ val = cargv[ i ] + STRLENOF( SCOPESTR "=" );
+ for ( j=0; !BER_BVISNULL(&scopes[j].key); j++ ) {
+ if (!strncasecmp( val, scopes[j].key.bv_val,
+ scopes[j].key.bv_len )) {
+ while (!scopes[j].val) j--;
+ si->si_scope = scopes[j].val;
+ break;
+ }
+ }
+ if ( BER_BVISNULL(&scopes[j].key) ) {
+ fprintf( stderr, "Error: parse_syncrepl_line: "
+ "unknown scope \"%s\"\n", val);
+ return -1;
+ }
+ } else if ( !strncasecmp( cargv[ i ], ATTRSONLYSTR "=",
+ STRLENOF( ATTRSONLYSTR "=" ) ) )
+ {
+ si->si_attrsonly = 1;
+ } else if ( !strncasecmp( cargv[ i ], ATTRSSTR "=",
+ STRLENOF( ATTRSSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( ATTRSSTR "=" );
+ if ( !strncasecmp( val, ":include:", STRLENOF(":include:") ) ) {
+ char *attr_fname;
+ attr_fname = ch_strdup( val + STRLENOF(":include:") );
+ si->si_anlist = file2anlist( si->si_anlist, attr_fname, " ,\t" );
+ if ( si->si_anlist == NULL ) {
+ ch_free( attr_fname );
+ return -1;
+ }
+ si->si_anfile = attr_fname;
+ } else {
+ char *str, *s, *next;
+ char delimstr[] = " ,\t";
+ str = ch_strdup( val );
+ for ( s = ldap_pvt_strtok( str, delimstr, &next );
+ s != NULL;
+ s = ldap_pvt_strtok( NULL, delimstr, &next ) )
+ {
+ if ( strlen(s) == 1 && *s == '*' ) {
+ si->si_allattrs = 1;
+ *(val + ( s - str )) = delimstr[0];
+ }
+ if ( strlen(s) == 1 && *s == '+' ) {
+ si->si_allopattrs = 1;
+ *(val + ( s - str )) = delimstr[0];
+ }
+ }
+ ch_free( str );
+ si->si_anlist = str2anlist( si->si_anlist, val, " ,\t" );
+ if ( si->si_anlist == NULL ) {
+ return -1;
+ }
+ }
+ } else if ( !strncasecmp( cargv[ i ], EXATTRSSTR "=",
+ STRLENOF( EXATTRSSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( EXATTRSSTR "=" );
+ if ( !strncasecmp( val, ":include:", STRLENOF(":include:") )) {
+ char *attr_fname;
+ attr_fname = ch_strdup( val + STRLENOF(":include:") );
+ si->si_exanlist = file2anlist(
+ si->si_exanlist, attr_fname, " ,\t" );
+ if ( si->si_exanlist == NULL ) {
+ ch_free( attr_fname );
+ return -1;
+ }
+ ch_free( attr_fname );
+ } else {
+ si->si_exanlist = str2anlist( si->si_exanlist, val, " ,\t" );
+ if ( si->si_exanlist == NULL ) {
+ return -1;
+ }
+ }
+ } else if ( !strncasecmp( cargv[ i ], TYPESTR "=",
+ STRLENOF( TYPESTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( TYPESTR "=" );
+ if ( !strncasecmp( val, "refreshOnly",
+ STRLENOF("refreshOnly") ))
+ {
+ si->si_type = LDAP_SYNC_REFRESH_ONLY;
+ } else if ( !strncasecmp( val, "refreshAndPersist",
+ STRLENOF("refreshAndPersist") ))
+ {
+ si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST;
+ si->si_interval = 60;
+ } else {
+ fprintf( stderr, "Error: parse_syncrepl_line: "
+ "unknown sync type \"%s\"\n", val);
+ return -1;
+ }
+ } else if ( !strncasecmp( cargv[ i ], INTERVALSTR "=",
+ STRLENOF( INTERVALSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( INTERVALSTR "=" );
+ 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;
+ }
+ 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 "=",
+ STRLENOF( RETRYSTR "=" ) ) )
+ {
+ char **retry_list;
+ int j, k, n;
+
+ val = cargv[ i ] + STRLENOF( RETRYSTR "=" );
+ retry_list = (char **) ch_calloc( 1, sizeof( char * ));
+ retry_list[0] = NULL;
+
+ slap_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 "=",
+ STRLENOF( MANAGEDSAITSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( MANAGEDSAITSTR "=" );
+ si->si_manageDSAit = atoi( val );
+ } else if ( !strncasecmp( cargv[ i ], SLIMITSTR "=",
+ STRLENOF( SLIMITSTR "=") ) )
+ {
+ val = cargv[ i ] + STRLENOF( SLIMITSTR "=" );
+ si->si_slimit = atoi( val );
+ } else if ( !strncasecmp( cargv[ i ], TLIMITSTR "=",
+ STRLENOF( TLIMITSTR "=" ) ) )
+ {
+ val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
+ si->si_tlimit = atoi( val );
+ } else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
+ fprintf( stderr, "Error: parse_syncrepl_line: "
+ "unknown keyword \"%s\"\n", cargv[ i ] );
+ return -1;
+ }
+ }
+
+ if ( gots != GOT_ALL ) {
+ fprintf( stderr,
+ "Error: Malformed \"syncrepl\" line in slapd config file" );
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+add_syncrepl(
+ Backend *be,
+ char **cargv,
+ int cargc
+)
+{
+ syncinfo_t *si;
+ int rc = 0;
+
+ if ( !( be->be_search && be->be_add && be->be_modify && be->be_delete )) {
+ Debug( LDAP_DEBUG_ANY, "database %s does not support operations "
+ "required for syncrepl\n", be->be_type, 0, 0 );
+ return 1;
+ }
+ si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
+
+ if ( si == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
+ return 1;
+ }
+
+ si->si_bindconf.sb_tls = SB_TLS_OFF;
+ si->si_bindconf.sb_method = LDAP_AUTH_SIMPLE;
+ si->si_schemachecking = 0;
+ ber_str2bv( "(objectclass=*)", STRLENOF("(objectclass=*)"), 1,
+ &si->si_filterstr );
+ si->si_base.bv_val = NULL;
+ si->si_scope = LDAP_SCOPE_SUBTREE;
+ si->si_attrsonly = 0;
+ si->si_anlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
+ si->si_exanlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
+ si->si_attrs = NULL;
+ si->si_allattrs = 0;
+ si->si_allopattrs = 0;
+ si->si_exattrs = NULL;
+ si->si_type = LDAP_SYNC_REFRESH_ONLY;
+ si->si_interval = 86400;
+ si->si_retryinterval = NULL;
+ si->si_retrynum_init = NULL;
+ si->si_retrynum = NULL;
+ si->si_manageDSAit = 0;
+ si->si_tlimit = 0;
+ si->si_slimit = 0;
+
+ si->si_presentlist = NULL;
+ LDAP_LIST_INIT( &si->si_nonpresentlist );
+ ldap_pvt_thread_mutex_init( &si->si_mutex );
+
+ rc = parse_syncrepl_line( cargv, cargc, si );
+
+ if ( rc < 0 ) {
+ Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
+ syncinfo_free( si );
+ return 1;
+ } else {
+ Debug( LDAP_DEBUG_CONFIG,
+ "Config: ** successfully added syncrepl \"%s\"\n",
+ BER_BVISNULL( &si->si_provideruri ) ?
+ "(null)" : si->si_provideruri.bv_val, 0, 0 );
+ if ( !si->si_schemachecking ) {
+ SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
+ }
+ si->si_be = be;
+ be->be_syncinfo = si;
+ init_syncrepl( si );
+ ldap_pvt_runqueue_insert( &slapd_rq,si->si_interval,do_syncrepl,si );
+ return 0;
+ }
+}
+
+static void
+syncrepl_unparse( syncinfo_t *si, struct berval *bv )
+{
+ struct berval bc;
+ char buf[BUFSIZ*2], *ptr;
+ int i, len;
+
+ bindconf_unparse( &si->si_bindconf, &bc );
+ ptr = buf;
+ ptr += sprintf( ptr, IDSTR "=%03d " PROVIDERSTR "=%s",
+ si->si_rid, si->si_provideruri.bv_val );
+ if ( !BER_BVISNULL( &bc )) {
+ ptr = lutil_strcopy( ptr, bc.bv_val );
+ free( bc.bv_val );
+ }
+ if ( !BER_BVISEMPTY( &si->si_filterstr )) {
+ ptr = lutil_strcopy( ptr, " " FILTERSTR "=\"" );
+ ptr = lutil_strcopy( ptr, si->si_filterstr.bv_val );
+ *ptr++ = '"';
+ }
+ if ( !BER_BVISNULL( &si->si_base )) {
+ ptr = lutil_strcopy( ptr, " " SEARCHBASESTR "=\"" );
+ ptr = lutil_strcopy( ptr, si->si_base.bv_val );
+ *ptr++ = '"';
+ }
+ for (i=0; !BER_BVISNULL(&scopes[i].key);i++) {
+ if ( si->si_scope == scopes[i].val ) {
+ 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 ( si->si_anfile ) {
+ ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:" );
+ ptr = lutil_strcopy( ptr, si->si_anfile );
+ } else if ( si->si_allattrs || si->si_allopattrs ||
+ ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) {
+ char *old;
+ ptr = lutil_strcopy( ptr, " " ATTRSSTR "=\"" );
+ old = ptr;
+ ptr = anlist_unparse( si->si_anlist, ptr );
+ if ( si->si_allattrs ) {
+ if ( old != ptr ) *ptr++ = ',';
+ *ptr++ = '*';
+ }
+ if ( si->si_allopattrs ) {
+ if ( old != ptr ) *ptr++ = ',';
+ *ptr++ = '+';
+ }
+ *ptr++ = '"';
+ }
+ if ( si->si_exanlist && !BER_BVISNULL(&si->si_exanlist[0].an_name) ) {
+ ptr = lutil_strcopy( ptr, " " EXATTRSSTR "=" );
+ ptr = anlist_unparse( si->si_exanlist, ptr );
+ }
+ ptr = lutil_strcopy( ptr, " " SCHEMASTR "=" );
+ ptr = lutil_strcopy( ptr, si->si_schemachecking ? "on" : "off" );
+
+ ptr = lutil_strcopy( ptr, " " TYPESTR "=" );
+ ptr = lutil_strcopy( ptr, si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ?
+ "refreshAndPersist" : "refreshOnly" );
+
+ if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
+ int dd, hh, mm, ss;
+
+ dd = si->si_interval;
+ ss = dd % 60;
+ dd /= 60;
+ mm = dd % 60;
+ dd /= 60;
+ hh = dd % 24;
+ dd /= 24;
+ ptr = lutil_strcopy( ptr, " " INTERVALSTR "=" );
+ ptr += sprintf( ptr, "%02d:%02d:%02d:%02d", dd, hh, mm, ss );
+ } else if ( si->si_retryinterval ) {
+ int space=0;
+ ptr = lutil_strcopy( ptr, " " RETRYSTR "=\"" );
+ for (i=0; si->si_retryinterval[i]; i++) {
+ if ( space ) *ptr++ = ' ';
+ space = 1;
+ ptr += sprintf( ptr, "%d", si->si_retryinterval[i] );
+ if ( si->si_retrynum_init[i] == -1 )
+ *ptr++ = '+';
+ else
+ ptr += sprintf( ptr, "%d", si->si_retrynum_init );
+ }
+ *ptr++ = '"';
+ }
+
+ if ( si->si_slimit ) {
+ ptr = lutil_strcopy( ptr, " " SLIMITSTR "=" );
+ ptr += sprintf( ptr, "%d", si->si_slimit );
+ }
+
+ if ( si->si_tlimit ) {
+ ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
+ ptr += sprintf( ptr, "%d", si->si_tlimit );
+ }
+ bc.bv_len = ptr - buf;
+ bc.bv_val = buf;
+ ber_dupbv( bv, &bc );
+}
+
+int
+syncrepl_config(ConfigArgs *c) {
+ if (c->op == SLAP_CONFIG_EMIT) {
+ if ( c->be->be_syncinfo ) {
+ struct berval bv;
+ syncrepl_unparse( c->be->be_syncinfo, &bv );
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ return 0;
+ }
+ return 1;
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ struct re_s *re;
+
+ if ( c->be->be_syncinfo ) {
+ re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, c->be->be_syncinfo );
+ 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;
+ }
+ return 0;
+ }
+ if(SLAP_SHADOW(c->be)) {
+ Debug(LDAP_DEBUG_ANY, "%s: "
+ "syncrepl: database already shadowed.\n",
+ c->log, 0, 0);
+ return(1);
+ } else if(add_syncrepl(c->be, c->argv, c->argc)) {
+ return(1);
+ }
+ SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SYNC_SHADOW);
+ return(0);
+}