mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
Isolate syncrepl stuff in syncrepl.c
This commit is contained in:
parent
2dec29f265
commit
8f78d064ee
@ -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 )
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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((
|
||||
|
@ -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;
|
||||
|
@ -27,15 +27,70 @@
|
||||
#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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user