]> git.sur5r.net Git - openldap/commitdiff
Isolate syncrepl stuff in syncrepl.c
authorHoward Chu <hyc@openldap.org>
Fri, 22 Apr 2005 14:38:35 +0000 (14:38 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 22 Apr 2005 14:38:35 +0000 (14:38 +0000)
servers/slapd/bconfig.c
servers/slapd/config.h
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/syncrepl.c

index 01bc45880bab549ecb06f64d24c2b75f84a2f9aa..1a278345e37a0f45fa38852d068716e6d8cc13a8 100644 (file)
@@ -33,7 +33,6 @@
 #endif
 
 #include <lutil.h>
-#include <ldap_rq.h>
 
 #include "config.h"
 
@@ -111,9 +110,6 @@ static ConfigFile cf_prv, *cfn = &cf_prv;
 
 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 );
 
@@ -138,7 +134,6 @@ static ConfigDriver config_requires;
 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;
@@ -147,6 +142,7 @@ static ConfigDriver config_include;
 static ConfigDriver config_tls_option;
 static ConfigDriver config_tls_config;
 #endif
+extern ConfigDriver syncrepl_config;
 
 enum {
        CFG_ACL = 1,
@@ -510,7 +506,7 @@ ConfigTable config_back_cf_table[] = {
                &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' "
@@ -1846,43 +1842,6 @@ config_loglevel(ConfigArgs *c) {
        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;
@@ -1987,7 +1946,7 @@ config_security(ConfigArgs *c) {
        return(0);
 }
 
-static char *
+char *
 anlist_unparse( AttributeName *an, char *ptr ) {
        int comma = 0;
 
@@ -2351,529 +2310,6 @@ config_tls_config(ConfigArgs *c) {
 }
 #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 )
 {
index 30b2d199e80c112efd4ffc717dd78f0b4fa5a754..e56e5c289f0ed34d4c1277ab29daa3394b97c641 100644 (file)
@@ -65,7 +65,6 @@ typedef enum {
 #define ARG_MAGIC      0x80000000
 
 #define ARG_BAD_CONF   0xdead0000      /* overload return values */
-#define ARG_UNKNOWN    0xc0de0000
 
 extern ConfigTable config_back_cf_table[];
 
@@ -73,12 +72,6 @@ typedef struct ConfigOCs {
        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;
index 65f191c775d010b0adbc45e3254d2e00d13c28a5..9dff1bda140e224a3eb1536b8adb17f417046a7e 100644 (file)
@@ -479,6 +479,7 @@ LDAP_SLAPD_F (int) bindconf_unparse LDAP_P((
 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;
@@ -1353,27 +1354,9 @@ LDAP_SLAPD_F (Filter *) str2filter_x LDAP_P(( Operation *op, const char *str ));
  * 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((
index 67f73a0d2fd793bf0e7be3feefd063b3e91c803b..3537d3f9079d6ef6232970e58a15450c851fb66d 100644 (file)
@@ -1571,17 +1571,13 @@ typedef BackendDB Backend;
  * 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;
@@ -1591,40 +1587,6 @@ struct sync_cookie {
 
 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
@@ -1798,7 +1760,7 @@ struct slap_backend_db {
        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;
index e41329f1f07b09968cac5ce4f189cab092d4b287..767ed876669f68d67088c21ad8694993b70c97d1 100644 (file)
 #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 * );
@@ -44,7 +99,7 @@ static int null_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;
@@ -2173,3 +2228,560 @@ syncinfo_free( syncinfo_t *sie )
        }
        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);
+}