mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-21 22:34:08 -05:00
Add syncdata keyword, to select different sync data formats. Defaults
to "default", can be set to "accesslog" or "changelog". changelog is not fully implemented yet.
This commit is contained in:
parent
285f841bd6
commit
37ad7614de
1 changed files with 301 additions and 1 deletions
|
|
@ -41,6 +41,10 @@ struct nonpresent_entry {
|
|||
LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
|
||||
};
|
||||
|
||||
#define SYNCDATA_DEFAULT 0 /* entries are plain LDAP entries */
|
||||
#define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */
|
||||
#define SYNCDATA_CHANGELOG 2 /* entries are changelog format */
|
||||
|
||||
typedef struct syncinfo_s {
|
||||
struct slap_backend_db *si_be;
|
||||
struct re_s *si_re;
|
||||
|
|
@ -70,6 +74,7 @@ typedef struct syncinfo_s {
|
|||
int si_tlimit;
|
||||
int si_refreshDelete;
|
||||
int si_refreshPresent;
|
||||
int si_syncdata;
|
||||
Avlnode *si_presentlist;
|
||||
LDAP *si_ld;
|
||||
LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
|
||||
|
|
@ -79,6 +84,8 @@ typedef struct syncinfo_s {
|
|||
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_op(
|
||||
syncinfo_t *, Operation *, LDAPMessage * );
|
||||
static int syncrepl_message_to_entry(
|
||||
syncinfo_t *, Operation *, LDAPMessage *,
|
||||
Modifications **, Entry **, int );
|
||||
|
|
@ -621,7 +628,14 @@ do_syncrep2(
|
|||
slap_parse_sync_cookie( &syncCookie, NULL );
|
||||
}
|
||||
}
|
||||
if ( syncrepl_message_to_entry( si, op, msg,
|
||||
if ( si->si_syncdata ) {
|
||||
entry = NULL;
|
||||
modlist = NULL;
|
||||
if ( syncrepl_message_to_op( si, op, msg ) == LDAP_SUCCESS &&
|
||||
!BER_BVISNULL( &syncCookie.octet_str ) ) {
|
||||
syncrepl_updateCookie( si, op, psub, &syncCookie );
|
||||
}
|
||||
} else if ( syncrepl_message_to_entry( si, op, msg,
|
||||
&modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
|
||||
rc_efree = syncrepl_entry( si, op, entry, &modlist,
|
||||
syncstate, &syncUUID, &syncCookie_req, &syncCookie.ctxcsn );
|
||||
|
|
@ -1025,6 +1039,270 @@ do_syncrepl(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct logschema {
|
||||
struct berval ls_dn;
|
||||
struct berval ls_req;
|
||||
struct berval ls_mod;
|
||||
struct berval ls_newRdn;
|
||||
struct berval ls_delRdn;
|
||||
struct berval ls_newSup;
|
||||
} logschema;
|
||||
|
||||
static logschema changelog_sc = {
|
||||
BER_BVC("targetDN"),
|
||||
BER_BVC("changeType"),
|
||||
BER_BVC("changes"),
|
||||
BER_BVC("newRDN"),
|
||||
BER_BVC("deleteOldRDN"),
|
||||
BER_BVC("newSuperior")
|
||||
};
|
||||
|
||||
static logschema accesslog_sc = {
|
||||
BER_BVC("reqDN"),
|
||||
BER_BVC("reqType"),
|
||||
BER_BVC("reqMod"),
|
||||
BER_BVC("reqNewRDN"),
|
||||
BER_BVC("reqDeleteOldRDN"),
|
||||
BER_BVC("reqNewSuperior")
|
||||
};
|
||||
|
||||
static slap_verbmasks modops[] = {
|
||||
{ BER_BVC("add"), LDAP_REQ_ADD },
|
||||
{ BER_BVC("delete"), LDAP_REQ_DELETE },
|
||||
{ BER_BVC("modify"), LDAP_REQ_MODIFY },
|
||||
{ BER_BVC("modrdn"), LDAP_REQ_MODRDN},
|
||||
{ BER_BVNULL, 0 }
|
||||
};
|
||||
|
||||
static Modifications *
|
||||
syncrepl_accesslog_mods(
|
||||
syncinfo_t *si,
|
||||
struct berval *vals
|
||||
)
|
||||
{
|
||||
char *colon;
|
||||
const char *text;
|
||||
AttributeDescription *ad;
|
||||
struct berval bv, bv2;
|
||||
short op;
|
||||
Modifications *mod = NULL, *modlist = NULL, **modtail;
|
||||
int i;
|
||||
|
||||
modtail = &modlist;
|
||||
|
||||
for (i=0; !BER_BVISNULL( &vals[i] ); i++) {
|
||||
ad = NULL;
|
||||
bv = vals[i];
|
||||
|
||||
colon = strchr( bv.bv_val, ':' );
|
||||
if ( !colon )
|
||||
continue; /* invalid */
|
||||
bv.bv_len = colon - bv.bv_val;
|
||||
if ( slap_bv2ad( &bv, &ad, &text )) {
|
||||
/* Invalid */
|
||||
continue;
|
||||
}
|
||||
/* Ignore dynamically generated attrs */
|
||||
if ( ad->ad_type->sat_flags & SLAP_AT_DYNAMIC )
|
||||
continue;
|
||||
/* Ignore excluded attrs */
|
||||
if ( ldap_charray_inlist( si->si_exattrs,
|
||||
ad->ad_type->sat_cname.bv_val ))
|
||||
continue;
|
||||
|
||||
switch(colon[1]) {
|
||||
case '+': op = LDAP_MOD_ADD; break;
|
||||
case '-': op = LDAP_MOD_DELETE; break;
|
||||
case '=': op = LDAP_MOD_REPLACE; break;
|
||||
case '#': op = LDAP_MOD_INCREMENT; break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
if ( !mod || ad != mod->sml_desc || op != mod->sml_op ) {
|
||||
mod = (Modifications *) ch_malloc( sizeof( Modifications ));
|
||||
mod->sml_flags = 0;
|
||||
mod->sml_op = op;
|
||||
mod->sml_next = NULL;
|
||||
mod->sml_desc = ad;
|
||||
mod->sml_type = ad->ad_cname;
|
||||
mod->sml_values = NULL;
|
||||
mod->sml_nvalues = NULL;
|
||||
|
||||
*modtail = mod;
|
||||
modtail = &mod->sml_next;
|
||||
}
|
||||
bv.bv_val = colon + 3;
|
||||
bv.bv_len = vals[i].bv_len - ( bv.bv_val - vals[i].bv_val );
|
||||
ber_dupbv( &bv2, &bv );
|
||||
ber_bvarray_add( &mod->sml_values, &bv2 );
|
||||
}
|
||||
return modlist;
|
||||
}
|
||||
|
||||
static Modifications *
|
||||
syncrepl_changelog_mods(
|
||||
syncinfo_t *si,
|
||||
struct berval *vals
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
syncrepl_message_to_op(
|
||||
syncinfo_t *si,
|
||||
Operation *op,
|
||||
LDAPMessage *msg
|
||||
)
|
||||
{
|
||||
BerElement *ber = NULL;
|
||||
Modifications *modlist = NULL;
|
||||
logschema *ls;
|
||||
SlapReply rs = { REP_RESULT };
|
||||
slap_callback cb = { NULL, null_callback, NULL, NULL };
|
||||
|
||||
const char *text;
|
||||
char txtbuf[SLAP_TEXT_BUFLEN];
|
||||
size_t textlen = sizeof txtbuf;
|
||||
|
||||
struct berval bdn, dn = BER_BVNULL, ndn;
|
||||
struct berval bv, *bvals = NULL;
|
||||
struct berval rdn = BER_BVNULL, sup = BER_BVNULL,
|
||||
prdn = BER_BVNULL, nrdn = BER_BVNULL,
|
||||
psup = BER_BVNULL, nsup = BER_BVNULL;
|
||||
int rc, deleteOldRdn = 0;
|
||||
|
||||
if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
|
||||
ls = &accesslog_sc;
|
||||
else
|
||||
ls = &changelog_sc;
|
||||
|
||||
rc = ldap_get_dn_ber( si->si_ld, msg, &ber, &bdn );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_message_to_op : dn get failed (%d)", rc, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
op->o_tag = LBER_DEFAULT;
|
||||
|
||||
while (( rc = ldap_get_attribute_ber( si->si_ld, msg, ber, &bv, &bvals ))
|
||||
== LDAP_SUCCESS ) {
|
||||
if ( bv.bv_val == NULL )
|
||||
break;
|
||||
|
||||
if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn )) {
|
||||
bdn = bvals[0];
|
||||
dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
|
||||
ber_dupbv( &op->o_req_dn, &dn );
|
||||
ber_dupbv( &op->o_req_ndn, &ndn );
|
||||
slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
|
||||
slap_sl_free( dn.bv_val, op->o_tmpmemctx );
|
||||
} else if ( !ber_bvstrcasecmp( &bv, &ls->ls_req )) {
|
||||
int i = verb_to_mask( bvals[0].bv_val, modops );
|
||||
if ( i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_message_to_op : unknown op %s",
|
||||
bvals[0].bv_val, 0, 0 );
|
||||
ch_free( bvals );
|
||||
goto done;
|
||||
}
|
||||
op->o_tag = modops[i].mask;
|
||||
} else if ( !ber_bvstrcasecmp( &bv, &ls->ls_mod )) {
|
||||
/* Parse attribute into modlist */
|
||||
if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
|
||||
modlist = syncrepl_accesslog_mods( si, bvals );
|
||||
else
|
||||
modlist = syncrepl_changelog_mods( si, bvals );
|
||||
} else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newRdn )) {
|
||||
rdn = bvals[0];
|
||||
} else if ( !ber_bvstrcasecmp( &bv, &ls->ls_delRdn )) {
|
||||
if ( !ber_bvstrcasecmp( &slap_true_bv, bvals ))
|
||||
deleteOldRdn = 1;
|
||||
} else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newSup )) {
|
||||
sup = bvals[0];
|
||||
}
|
||||
ch_free( bvals );
|
||||
}
|
||||
|
||||
/* If we didn't get a mod type or a target DN, bail out */
|
||||
if ( op->o_tag == LBER_DEFAULT || BER_BVISNULL( &dn ))
|
||||
goto done;
|
||||
|
||||
op->o_callback = &cb;
|
||||
|
||||
switch( op->o_tag ) {
|
||||
case LDAP_REQ_ADD:
|
||||
case LDAP_REQ_MODIFY:
|
||||
/* If we didn't get required data, bail */
|
||||
if ( !modlist ) goto done;
|
||||
|
||||
rc = slap_mods_check( modlist, &text, txtbuf, textlen, NULL );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: mods check (%s)\n",
|
||||
text, 0, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( op->o_tag == LDAP_REQ_ADD ) {
|
||||
op->ora_e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
|
||||
op->ora_e->e_name = op->o_req_dn;
|
||||
op->ora_e->e_nname = op->o_req_ndn;
|
||||
rc = slap_mods2entry( modlist, &op->ora_e, 1, 0, &text, txtbuf, textlen);
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: mods2entry (%s)\n",
|
||||
text, 0, 0 );
|
||||
} else {
|
||||
rc = op->o_bd->be_add( op, &rs );
|
||||
}
|
||||
be_entry_release_w( op, op->ora_e );
|
||||
} else {
|
||||
op->orm_modlist = modlist;
|
||||
rc = op->o_bd->be_modify( op, &rs );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
if ( BER_BVISNULL( &rdn )) goto done;
|
||||
|
||||
if ( rdnPretty( NULL, &rdn, &prdn, NULL ))
|
||||
goto done;
|
||||
if ( rdnNormalize( 0, NULL, NULL, &rdn, &nrdn, NULL ))
|
||||
goto done;
|
||||
if ( !BER_BVISNULL( &sup )) {
|
||||
if ( dnPrettyNormal( NULL, &sup, &psup, &nsup, NULL ))
|
||||
goto done;
|
||||
op->orr_newSup = &psup;
|
||||
op->orr_nnewSup = ⊅
|
||||
}
|
||||
op->orr_newrdn = prdn;
|
||||
op->orr_nnewrdn = nrdn;
|
||||
op->orr_deleteoldrdn = deleteOldRdn;
|
||||
rc = op->o_bd->be_modrdn( op, &rs );
|
||||
break;
|
||||
}
|
||||
done:
|
||||
if ( modlist )
|
||||
slap_mods_free( modlist, op->o_tag != LDAP_REQ_ADD );
|
||||
if ( !BER_BVISNULL( &rdn )) {
|
||||
if ( !BER_BVISNULL( &nsup ))
|
||||
ch_free( nsup.bv_val );
|
||||
if ( !BER_BVISNULL( &psup ))
|
||||
ch_free( psup.bv_val );
|
||||
if ( !BER_BVISNULL( &nrdn ))
|
||||
ch_free( nrdn.bv_val );
|
||||
if ( !BER_BVISNULL( &prdn ))
|
||||
ch_free( prdn.bv_val );
|
||||
}
|
||||
ber_free ( ber, 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
syncrepl_message_to_entry(
|
||||
syncinfo_t *si,
|
||||
|
|
@ -2254,6 +2532,7 @@ syncinfo_free( syncinfo_t *sie )
|
|||
#define RETRYSTR "retry"
|
||||
#define SLIMITSTR "sizelimit"
|
||||
#define TLIMITSTR "timelimit"
|
||||
#define SYNCDATASTR "syncdata"
|
||||
|
||||
/* FIXME: undocumented */
|
||||
#define OLDAUTHCSTR "bindprincipal"
|
||||
|
|
@ -2291,6 +2570,13 @@ static struct {
|
|||
{ BER_BVNULL, 0 }
|
||||
};
|
||||
|
||||
static slap_verbmasks datamodes[] = {
|
||||
{ BER_BVC("default"), SYNCDATA_DEFAULT },
|
||||
{ BER_BVC("accesslog"), SYNCDATA_ACCESSLOG },
|
||||
{ BER_BVC("changelog"), SYNCDATA_CHANGELOG },
|
||||
{ BER_BVNULL, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
parse_syncrepl_line(
|
||||
char **cargv,
|
||||
|
|
@ -2338,6 +2624,8 @@ parse_syncrepl_line(
|
|||
STRLENOF( FILTERSTR "=" ) ) )
|
||||
{
|
||||
val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
|
||||
if ( si->si_filterstr.bv_val )
|
||||
ch_free( si->si_filterstr.bv_val );
|
||||
ber_str2bv( val, 0, 1, &si->si_filterstr );
|
||||
} else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
|
||||
STRLENOF( SEARCHBASESTR "=" ) ) )
|
||||
|
|
@ -2565,6 +2853,11 @@ parse_syncrepl_line(
|
|||
{
|
||||
val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
|
||||
si->si_tlimit = atoi( val );
|
||||
} else if ( !strncasecmp( cargv[ i ], SYNCDATASTR "=",
|
||||
STRLENOF( SYNCDATASTR "=" ) ) )
|
||||
{
|
||||
val = cargv[ i ] + STRLENOF( SYNCDATASTR "=" );
|
||||
si->si_syncdata = verb_to_mask( val, datamodes );
|
||||
} else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
|
||||
fprintf( stderr, "Error: parse_syncrepl_line: "
|
||||
"unknown keyword \"%s\"\n", cargv[ i ] );
|
||||
|
|
@ -2758,6 +3051,13 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
|
|||
ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
|
||||
ptr += sprintf( ptr, "%d", si->si_tlimit );
|
||||
}
|
||||
|
||||
if ( si->si_syncdata ) {
|
||||
if ( enum_to_verb( datamodes, si->si_syncdata, &bc ) >= 0 ) {
|
||||
ptr = lutil_strcopy( ptr, " " SYNCDATASTR "=" );
|
||||
ptr = lutil_strcopy( ptr, bc.bv_val );
|
||||
}
|
||||
}
|
||||
bc.bv_len = ptr - buf;
|
||||
bc.bv_val = buf;
|
||||
ber_dupbv( bv, &bc );
|
||||
|
|
|
|||
Loading…
Reference in a new issue