syncrepl.c 86.6 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* syncrepl.c -- Replication Engine which uses the LDAP Sync protocol */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2003-2005 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
 * Portions Copyright 2003 by IBM Corporation.
 * Portions Copyright 2003 by Howard Chu, Symas Corporation.
 * All rights reserved.
9
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
11
12
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
13
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
14
15
16
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
17
 */
18
19
20
21
22
23
24
25
26
27
28
29

#include "portable.h"

#include <stdio.h>

#include <ac/string.h>
#include <ac/socket.h>

#include "lutil.h"
#include "slap.h"
#include "lutil_ldap.h"

30
31
#include "config.h"

32
33
#include "ldap_rq.h"

34
35
36
37
38
39
struct nonpresent_entry {
	struct berval *npe_name;
	struct berval *npe_nname;
	LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
};

Kurt Zeilenga's avatar
Kurt Zeilenga committed
40
41
42
43
#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 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
44
45
46
#define	SYNCLOG_LOGGING		0	/* doing a log-based update */
#define	SYNCLOG_FALLBACK	1	/* doing a full refresh */

47
48
49
50
51
52
typedef struct syncinfo_s {
	struct slap_backend_db *si_be;
	struct re_s			*si_re;
	long				si_rid;
	slap_bindconf		si_bindconf;
	struct berval		si_base;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
53
54
55
	struct berval		si_logbase;
	struct berval		si_filterstr;
	struct berval		si_logfilterstr;
56
57
58
59
60
61
62
63
64
65
	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;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
66
67
	int					si_type;	/* the active type */
	int					si_ctype;	/* the configured type */
68
69
70
71
72
73
74
75
76
77
	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;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
78
	int					si_syncdata;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
79
80
	int					si_logstate;
	int					si_conn_setup;
81
82
83
84
85
86
	Avlnode				*si_presentlist;
	LDAP				*si_ld;
	LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
	ldap_pvt_thread_mutex_t	si_mutex;
} syncinfo_t;

87
static int syncuuid_cmp( const void *, const void * );
88
static void avl_ber_bvfree( void * );
89
static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
90
91
static int syncrepl_message_to_op(
					syncinfo_t *, Operation *, LDAPMessage * );
92
93
94
95
96
97
98
99
100
101
102
103
104
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 * );
105

106
/* callback functions */
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
107
static int dn_callback( struct slap_op *, struct slap_rep * );
108
109
static int nonpresent_callback( struct slap_op *, struct slap_rep * );
static int null_callback( struct slap_op *, struct slap_rep * );
110

111
static AttributeDescription *sync_descs[4];
112

113
static void
114
init_syncrepl(syncinfo_t *si)
115
{
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
116
	int i, j, k, l, n;
117
	char **attrs, **exattrs;
118
119
120
121
122
123
124
125

	if ( !sync_descs[0] ) {
		sync_descs[0] = slap_schema.si_ad_objectClass;
		sync_descs[1] = slap_schema.si_ad_structuralObjectClass;
		sync_descs[2] = slap_schema.si_ad_entryCSN;
		sync_descs[3] = NULL;
	}

126
127
128
129
	if ( si->si_allattrs && si->si_allopattrs )
		attrs = NULL;
	else
		attrs = anlist2attrs( si->si_anlist );
130

131
132
133
134
135
136
137
138
139
	if ( attrs ) {
		if ( si->si_allattrs ) {
			i = 0;
			while ( attrs[i] ) {
				if ( !is_at_operational( at_find( attrs[i] ))) {
					for ( j = i; attrs[j] != NULL; j++ ) {
						if ( j == i )
							ch_free( attrs[i] );
						attrs[j] = attrs[j+1];
140
					}
141
142
				} else {
					i++;
143
144
				}
			}
145
			attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
146
147
			attrs[i] = ch_strdup("*");
			attrs[i + 1] = NULL;
148

149
150
151
152
153
154
155
156
157
158
159
160
161
		} else if ( si->si_allopattrs ) {
			i = 0;
			while ( attrs[i] ) {
				if ( is_at_operational( at_find( attrs[i] ))) {
					for ( j = i; attrs[j] != NULL; j++ ) {
						if ( j == i )
							ch_free( attrs[i] );
						attrs[j] = attrs[j+1];
					}
				} else {
					i++;
				}
			}
162
			attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
163
164
			attrs[i] = ch_strdup("+");
			attrs[i + 1] = NULL;
165
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
166

167
168
169
170
171
172
173
174
		for ( i = 0; sync_descs[i] != NULL; i++ ) {
			j = 0;
			while ( attrs[j] ) {
				if ( !strcmp( attrs[j], sync_descs[i]->ad_cname.bv_val )) {
					for ( k = j; attrs[k] != NULL; k++ ) {
						if ( k == j )
							ch_free( attrs[k] );
						attrs[k] = attrs[k+1];
175
					}
176
177
				} else {
					j++;
178
179
				}
			}
180
181
182
183
184
185
186
		}

		for ( n = 0; attrs[ n ] != NULL; n++ ) /* empty */;

		if ( si->si_allopattrs ) {
			attrs = ( char ** ) ch_realloc( attrs, (n + 2)*sizeof( char * ));
		} else {
187
			attrs = ( char ** ) ch_realloc( attrs, (n + 4)*sizeof( char * ));
188
189
190
		}

		if ( attrs == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
191
			Debug( LDAP_DEBUG_ANY, "out of memory\n", 0, 0, 0 );
192
193
194
195
196
197
		}

		/* Add Attributes */
		if ( si->si_allopattrs ) {
			attrs[n++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
		} else {
198
199
200
			for ( i = 0; sync_descs[ i ] != NULL; i++ ) {
				attrs[ n++ ] = ch_strdup ( sync_descs[i]->ad_cname.bv_val );
			}
201
		}
202
		attrs[ n ] = NULL;
203

204
	} else {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
205

206
		i = 0;
207
208
		if ( si->si_allattrs == si->si_allopattrs ) {
			attrs = (char**) ch_malloc( 3 * sizeof(char*) );
209
210
			attrs[i++] = ch_strdup( "*" );
			attrs[i++] = ch_strdup( "+" );
211
212
213
214
215
216
		} else if ( si->si_allattrs && !si->si_allopattrs ) {
			for ( n = 0; sync_descs[ n ] != NULL; n++ ) ;
			attrs = (char**) ch_malloc( (n+1)* sizeof(char*) );
			attrs[i++] = ch_strdup( "*" );
			for ( j = 1; sync_descs[ j ] != NULL; j++ ) {
				attrs[i++] = ch_strdup ( sync_descs[j]->ad_cname.bv_val );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
217
			}
218
219
220
221
		} else if ( !si->si_allattrs && si->si_allopattrs ) {
			attrs = (char**) ch_malloc( 3 * sizeof(char*) );
			attrs[i++] = ch_strdup( "+" );
			attrs[i++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
222
223
		}
		attrs[i] = NULL;
224
225
	}
	
226
227
228
229
230
	si->si_attrs = attrs;

	exattrs = anlist2attrs( si->si_exanlist );

	if ( exattrs ) {
231
232
		for ( n = 0; exattrs[n] != NULL; n++ ) ;

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
233
		for ( i = 0; sync_descs[i] != NULL; i++ ) {
234
235
236
			j = 0;
			while ( exattrs[j] != NULL ) {
				if ( !strcmp( exattrs[j], sync_descs[i]->ad_cname.bv_val )) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
237
					ch_free( exattrs[j] );
238
239
					for ( k = j; exattrs[k] != NULL; k++ ) {
						exattrs[k] = exattrs[k+1];
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
240
					}
241
242
				} else {
					j++;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
243
244
245
				}
			}
		}
246
247
248

		for ( i = 0; exattrs[i] != NULL; i++ ) {
			for ( j = 0; si->si_anlist[j].an_name.bv_val; j++ ) {
249
250
				ObjectClass	*oc;
				if ( ( oc = si->si_anlist[j].an_oc ) ) {
251
252
253
254
					k = 0;
					while ( oc->soc_required[k] ) {
						if ( !strcmp( exattrs[i],
							 oc->soc_required[k]->sat_cname.bv_val )) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
255
							ch_free( exattrs[i] );
256
257
258
259
260
							for ( l = i; exattrs[l]; l++ ) {
								exattrs[l] = exattrs[l+1];
							}
						} else {
							k++;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
261
262
263
264
265
						}
					}
				}
			}
		}
266
267

		for ( i = 0; exattrs[i] != NULL; i++ ) ;
268
269
270

		if ( i != n )
			exattrs = (char **) ch_realloc( exattrs, (i + 1)*sizeof(char *));
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
271
	}
272
273

	si->si_exattrs = exattrs;	
274
275
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
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")
};

303
static int
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
304
305
ldap_sync_search(
	syncinfo_t *si,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
306
	void *ctx )
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
307
{
308
309
310
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	LDAPControl c[2], *ctrls[3];
311
	struct timeval timeout;
312
	ber_int_t	msgid;
313
	int rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
314
315
316
317
318
319
	int rhint;
	char *base;
	char **attrs, *lattrs[8];
	char *filter;
	int attrsonly;
	int scope;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
320

321
322
323
	/* setup LDAP SYNC control */
	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
324

Kurt Zeilenga's avatar
Kurt Zeilenga committed
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	/* If we're using a log but we have no state, then fallback to
	 * normal mode for a full refresh.
	 */
	if ( si->si_syncdata && BER_BVISEMPTY( &si->si_syncCookie.ctxcsn ))
		si->si_logstate = SYNCLOG_FALLBACK;

	/* Use the log parameters if we're in log mode */
	if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) {
		logschema *ls;
		if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
			ls = &accesslog_sc;
		else
			ls = &changelog_sc;
		lattrs[0] = ls->ls_dn.bv_val;
		lattrs[1] = ls->ls_req.bv_val;
		lattrs[2] = ls->ls_mod.bv_val;
		lattrs[3] = ls->ls_newRdn.bv_val;
		lattrs[4] = ls->ls_delRdn.bv_val;
		lattrs[5] = ls->ls_newSup.bv_val;
		lattrs[6] = slap_schema.si_ad_entryCSN->ad_cname.bv_val;
		lattrs[7] = NULL;

		rhint = 0;
		base = si->si_logbase.bv_val;
		filter = si->si_logfilterstr.bv_val;
		attrs = lattrs;
		attrsonly = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
352
		scope = LDAP_SCOPE_SUBTREE;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	} else {
		rhint = 1;
		base = si->si_base.bv_val;
		filter = si->si_filterstr.bv_val;
		attrs = si->si_attrs;
		attrsonly = si->si_attrsonly;
		scope = si->si_scope;
	}
	if ( si->si_syncdata && si->si_logstate == SYNCLOG_FALLBACK ) {
		si->si_type = LDAP_SYNC_REFRESH_ONLY;
	} else {
		si->si_type = si->si_ctype;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
367
	if ( !BER_BVISNULL( &si->si_syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
368
	{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
369
370
		ber_printf( ber, "{eOb}",
			abs(si->si_type), &si->si_syncCookie.octet_str, rhint );
371
	} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
372
373
		ber_printf( ber, "{eb}",
			abs(si->si_type), rhint );
374
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
375

376
377
378
379
	if ( (rc = ber_flatten2( ber, &c[0].ldctl_value, 0 )) == LBER_ERROR ) {
		ber_free_buf( ber );
		return rc;
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
380

381
	c[0].ldctl_oid = LDAP_CONTROL_SYNC;
382
	c[0].ldctl_iscritical = si->si_type < 0;
383
	ctrls[0] = &c[0];
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
384

385
	if ( !BER_BVISNULL( &si->si_bindconf.sb_authzId ) ) {
386
		c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
387
		c[1].ldctl_value = si->si_bindconf.sb_authzId;
388
389
390
391
392
393
		c[1].ldctl_iscritical = 1;
		ctrls[1] = &c[1];
		ctrls[2] = NULL;
	} else {
		ctrls[1] = NULL;
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
394

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
395
	timeout.tv_sec = si->si_tlimit;
396
	timeout.tv_usec = 0;
397

Kurt Zeilenga's avatar
Kurt Zeilenga committed
398
	rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
399
		ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL,
400
		si->si_slimit, &msgid );
401
	ber_free_buf( ber );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
402
403
404
	return rc;
}

405
406
407
408
static int
do_syncrep1(
	Operation *op,
	syncinfo_t *si )
409
410
{
	int	rc;
411
	int cmdline_cookie_found = 0;
412

413
	struct sync_cookie	*sc = NULL;
414
	struct berval	*psub;
415
416
417
#ifdef HAVE_TLS
	void	*ssl;
#endif
418
419

	psub = &si->si_be->be_nsuffix[0];
420
421

	/* Init connection to master */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
422
	rc = ldap_initialize( &si->si_ld, si->si_bindconf.sb_uri.bv_val );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
423
	if ( rc != LDAP_SUCCESS ) {
424
		Debug( LDAP_DEBUG_ANY,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
425
			"do_syncrep1: ldap_initialize failed (%s)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
426
			si->si_bindconf.sb_uri.bv_val, 0, 0 );
427
		return rc;
428
429
	}

430
431
	op->o_protocol = LDAP_VERSION3;
	ldap_set_option( si->si_ld, LDAP_OPT_PROTOCOL_VERSION, &op->o_protocol );
432
433
434

	/* Bind to master */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
435
	if ( si->si_bindconf.sb_tls ) {
436
		rc = ldap_start_tls_s( si->si_ld, NULL, NULL );
437
438
439
		if( rc != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"%s: ldap_start_tls failed (%d)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
440
				si->si_bindconf.sb_tls == SB_TLS_CRITICAL ? "Error" : "Warning",
441
				rc, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
442
			if( si->si_bindconf.sb_tls == SB_TLS_CRITICAL ) goto done;
443
444
445
		}
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
446
	if ( si->si_bindconf.sb_method == LDAP_AUTH_SASL ) {
447
448
449
#ifdef HAVE_CYRUS_SASL
		void *defaults;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
450
		if ( si->si_bindconf.sb_secprops != NULL ) {
451
			rc = ldap_set_option( si->si_ld,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
452
				LDAP_OPT_X_SASL_SECPROPS, si->si_bindconf.sb_secprops);
453

454
			if( rc != LDAP_OPT_SUCCESS ) {
455
456
				Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
					"(%s,SECPROPS,\"%s\") failed!\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
457
					si->si_bindconf.sb_uri.bv_val, si->si_bindconf.sb_secprops, 0 );
458
				goto done;
459
460
461
			}
		}

462
463
464
465
466
467
		defaults = lutil_sasl_defaults( si->si_ld,
			si->si_bindconf.sb_saslmech.bv_val,
			si->si_bindconf.sb_realm.bv_val,
			si->si_bindconf.sb_authcId.bv_val,
			si->si_bindconf.sb_cred.bv_val,
			si->si_bindconf.sb_authzId.bv_val );
468

469
		rc = ldap_sasl_interactive_bind_s( si->si_ld,
470
471
				si->si_bindconf.sb_binddn.bv_val,
				si->si_bindconf.sb_saslmech.bv_val,
472
				NULL, NULL,
473
				LDAP_SASL_QUIET,
474
475
476
				lutil_sasl_interact,
				defaults );

477
478
		lutil_sasl_freedefs( defaults );

479
		/* FIXME: different error behaviors according to
480
481
482
		 *	1) return code
		 *	2) on err policy : exit, retry, backoff ...
		 */
483
		if ( rc != LDAP_SUCCESS ) {
484
485
			static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
486
			Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
487
488
				"ldap_sasl_interactive_bind_s failed (%d)\n",
				rc, 0, 0 );
489
490
491

			/* FIXME (see above comment) */
			/* if Kerberos credentials cache is not active, retry */
492
			if ( ber_bvcmp( &si->si_bindconf.sb_saslmech, &bv_GSSAPI ) == 0 &&
493
494
495
496
497
				rc == LDAP_LOCAL_ERROR )
			{
				rc = LDAP_SERVER_DOWN;
			}

498
			goto done;
499
500
		}
#else /* HAVE_CYRUS_SASL */
501
		/* Should never get here, we trapped this at config time */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
502
		assert(0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
503
		Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n", 0, 0, 0 );
504
505
		rc = LDAP_OTHER;
		goto done;
506
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
507

508
509
510
511
	} else if ( si->si_bindconf.sb_method == LDAP_AUTH_SIMPLE ) {
		rc = ldap_sasl_bind_s( si->si_ld,
			si->si_bindconf.sb_binddn.bv_val, LDAP_SASL_SIMPLE,
			&si->si_bindconf.sb_cred, NULL, NULL, NULL );
512
		if ( rc != LDAP_SUCCESS ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
513
			Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
514
				"ldap_sasl_bind_s failed (%d)\n", rc, 0, 0 );
515
			goto done;
516
517
518
		}
	}

519
520
521
	/* Set SSF to strongest of TLS, SASL SSFs */
	op->o_sasl_ssf = 0;
	op->o_tls_ssf = 0;
522
	op->o_transport_ssf = 0;
523
#ifdef HAVE_TLS
524
525
526
	if ( ldap_get_option( si->si_ld, LDAP_OPT_X_TLS_SSL_CTX, &ssl )
		== LDAP_SUCCESS && ssl != NULL )
	{
527
528
529
530
		op->o_tls_ssf = ldap_pvt_tls_get_strength( ssl );
	}
#endif /* HAVE_TLS */
	ldap_get_option( si->si_ld, LDAP_OPT_X_SASL_SSF, &op->o_sasl_ssf );
531
532
	op->o_ssf = ( op->o_sasl_ssf > op->o_tls_ssf )
		?  op->o_sasl_ssf : op->o_tls_ssf;
533

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
534

Kurt Zeilenga's avatar
Kurt Zeilenga committed
535
536
537
	if ( BER_BVISNULL( &si->si_syncCookie.octet_str )) {
		/* get contextCSN shadow replica from database */
		BerVarray csn = NULL;
538

Kurt Zeilenga's avatar
Kurt Zeilenga committed
539
540
541
		assert( si->si_rid < 1000 );
		op->o_req_ndn = op->o_bd->be_nsuffix[0];
		op->o_req_dn = op->o_req_ndn;
542

Kurt Zeilenga's avatar
Kurt Zeilenga committed
543
		/* try to read stored contextCSN */
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
544
		backend_attribute( op, NULL, &op->o_req_ndn,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
545
546
547
548
549
550
			slap_schema.si_ad_contextCSN, &csn, ACL_READ );
		if ( csn ) {
			ch_free( si->si_syncCookie.ctxcsn.bv_val );
			ber_dupbv( &si->si_syncCookie.ctxcsn, csn );
			ber_bvarray_free_x( csn, op->o_tmpmemctx );
		}
551

Kurt Zeilenga's avatar
Kurt Zeilenga committed
552
553
554
555
556
557
558
559
560
561
562
563
564
565
		si->si_syncCookie.rid = si->si_rid;

		LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) {
			if ( si->si_rid == sc->rid ) {
				cmdline_cookie_found = 1;
				break;
			}
		}

		if ( cmdline_cookie_found ) {
			/* cookie is supplied in the command line */

			LDAP_STAILQ_REMOVE( &slap_sync_cookie, sc, sync_cookie, sc_next );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
566
567
			/* ctxcsn wasn't parsed yet, do it now */
			slap_parse_sync_cookie( sc, op->o_tmpmemctx );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
568
			if ( BER_BVISNULL( &sc->ctxcsn ) ) {
569
570
571
				/* if cmdline cookie does not have ctxcsn */
				/* component, set it to an initial value */
				slap_init_sync_cookie_ctxcsn( sc );
572
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
573
			slap_sync_cookie_free( &si->si_syncCookie, 0 );
574
575
			slap_dup_sync_cookie( &si->si_syncCookie, sc );
			slap_sync_cookie_free( sc, 1 );
576
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
577

Kurt Zeilenga's avatar
Kurt Zeilenga committed
578
579
		slap_compose_sync_cookie( NULL, &si->si_syncCookie.octet_str,
			&si->si_syncCookie.ctxcsn, si->si_syncCookie.rid );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
580
581
582
	}

	rc = ldap_sync_search( si, op->o_tmpmemctx );
583

584
	if( rc != LDAP_SUCCESS ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
585
		Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
586
			"ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
587
588
589
590
591
	}

done:
	if ( rc ) {
		if ( si->si_ld ) {
592
			ldap_unbind_ext( si->si_ld, NULL, NULL );
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
			si->si_ld = NULL;
		}
	}

	return rc;
}

static int
do_syncrep2(
	Operation *op,
	syncinfo_t *si )
{
	LDAPControl	**rctrls = NULL;
	LDAPControl	*rctrlp;

	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *)&berbuf;

	LDAPMessage	*res = NULL;
	LDAPMessage	*msg = NULL;

	char		*retoid = NULL;
	struct berval	*retdata = NULL;

	Entry		*entry = NULL;

	int		syncstate;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
620
	struct berval	syncUUID = BER_BVNULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
621
622
	struct sync_cookie	syncCookie = { BER_BVNULL };
	struct sync_cookie	syncCookie_req = { BER_BVNULL };
Kurt Zeilenga's avatar
Kurt Zeilenga committed
623
	struct berval		cookie = BER_BVNULL;
624

625
	int	rc, err, i;
626
627
	ber_len_t	len;

628
	int rc_efree = 1;
629
630
631
632
633
634
635
636
637
638

	struct berval	*psub;
	Modifications	*modlist = NULL;

	const char		*text;
	int				match;

	struct timeval *tout_p = NULL;
	struct timeval tout = { 0, 0 };

639
640
	int		refreshDeletes = 0;
	int		refreshDone = 1;
641
	BerVarray syncUUIDs = NULL;
642
643
	ber_tag_t si_tag;

644
	if ( slapd_shutdown ) {
645
		rc = -2;
646
		goto done;
647
648
	}

649
650
651
	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

652
653
654
655
	Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2\n", 0, 0, 0 );

	psub = &si->si_be->be_nsuffix[0];

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
656
	slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
657

Kurt Zeilenga's avatar
Kurt Zeilenga committed
658
	if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
659
660
661
662
663
		tout_p = &tout;
	} else {
		tout_p = NULL;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
664
665
	while (( rc = ldap_result( si->si_ld, LDAP_RES_ANY, LDAP_MSG_ONE,
		tout_p, &res )) > 0 )
666
	{
667
		if ( slapd_shutdown ) {
668
669
			rc = -2;
			goto done;
670
		}
671
		for( msg = ldap_first_message( si->si_ld, res );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
672
673
			msg != NULL;
			msg = ldap_next_message( si->si_ld, msg ) )
674
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
675
676
677
678
			if ( slapd_shutdown ) {
				rc = -2;
				goto done;
			}
679
680
			switch( ldap_msgtype( msg ) ) {
			case LDAP_RES_SEARCH_ENTRY:
681
				ldap_get_entry_controls( si->si_ld, msg, &rctrls );
Howard Chu's avatar
Howard Chu committed
682
683
				/* we can't work without the control */
				if ( !rctrls ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
684
					Debug( LDAP_DEBUG_ANY, "do_syncrep2: "
685
686
						"got search entry without "
						"control\n", 0, 0, 0 );
Howard Chu's avatar
Howard Chu committed
687
688
689
690
691
					rc = -1;
					goto done;
				}
				rctrlp = *rctrls;
				ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
692
				ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
693
694
695
696
697
				/* FIXME: what if syncUUID is NULL or empty?
				 * (happens with back-sql...) */
				if ( BER_BVISEMPTY( &syncUUID ) ) {
					Debug( LDAP_DEBUG_ANY, "do_syncrep2: "
						"got empty syncUUID\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
698
					ldap_controls_free( rctrls );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
699
700
701
					rc = -1;
					goto done;
				}
702
				if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
703
					ber_scanf( ber, /*"{"*/ "m}", &cookie );
704
					if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
705
706
						ch_free( syncCookie.octet_str.bv_val );
						ber_dupbv( &syncCookie.octet_str, &cookie );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
707
					}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
708
					if ( !BER_BVISNULL( &syncCookie.octet_str ) )
709
					{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
710
						slap_parse_sync_cookie( &syncCookie, NULL );
711
					}
712
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
713
				if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
714
715
716
717
718
719
720
					entry = NULL;
					modlist = NULL;
					if ( syncrepl_message_to_op( si, op, msg ) == LDAP_SUCCESS &&
						!BER_BVISNULL( &syncCookie.ctxcsn ) ) {
						syncrepl_updateCookie( si, op, psub, &syncCookie );
					}
				} else if ( syncrepl_message_to_entry( si, op, msg,
721
					&modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
722
					rc_efree = syncrepl_entry( si, op, entry, &modlist,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
723
						syncstate, &syncUUID, &syncCookie_req, &syncCookie.ctxcsn );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
724
					if ( !BER_BVISNULL( &syncCookie.ctxcsn ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
725
					{
726
727
						syncrepl_updateCookie( si, op, psub, &syncCookie );
					}
728
				}
Howard Chu's avatar
Howard Chu committed
729
				ldap_controls_free( rctrls );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
730
				if ( modlist ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
731
					slap_mods_free( modlist, 1 );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
732
				}
733
				if ( rc_efree && entry ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
734
					entry_free( entry );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
735
				}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
736
				entry = NULL;
737
738
739
740
				break;

			case LDAP_RES_SEARCH_REFERENCE:
				Debug( LDAP_DEBUG_ANY,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
741
					"do_syncrep2: reference received error\n", 0, 0, 0 );
742
743
744
				break;

			case LDAP_RES_SEARCH_RESULT:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
745
746
				Debug( LDAP_DEBUG_SYNC,
					"do_syncrep2: LDAP_RES_SEARCH_RESULT\n", 0, 0, 0 );
747
				ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
748
					&rctrls, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
749
750
751
752
753
754
755
756
757
758
759
#ifdef LDAP_X_SYNC_REFRESH_REQUIRED
				if ( err == LDAP_X_SYNC_REFRESH_REQUIRED ) {
					/* map old result code to registered code */
					err = LDAP_SYNC_REFRESH_REQUIRED;
				}
#endif
				if ( err == LDAP_SYNC_REFRESH_REQUIRED ) {
					if ( si->si_logstate == SYNCLOG_LOGGING ) {
						si->si_logstate = SYNCLOG_FALLBACK;
					}
					rc = err;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
760
					goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
761
				}
762
763
				if ( rctrls ) {
					rctrlp = *rctrls;
764
					ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
765

766
					ber_scanf( ber, "{" /*"}"*/);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
767
					if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
768
						ber_scanf( ber, "m", &cookie );
769
						if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
770
771
							ch_free( syncCookie.octet_str.bv_val );
							ber_dupbv( &syncCookie.octet_str, &cookie);
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
772
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
773
						if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
774
						{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
775
							slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
776
						}
777
					}
778
779
780
781
					if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
					{
						ber_scanf( ber, "b", &refreshDeletes );
					}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
782
					ber_scanf( ber, /*"{"*/ "}" );
783
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
784
				if ( BER_BVISNULL( &syncCookie_req.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
785
					match = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
786
				} else if ( BER_BVISNULL( &syncCookie.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
787
788
789
790
791
					match = 1;
				} else {
					value_match( &match, slap_schema.si_ad_entryCSN,
						slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
						SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
792
						&syncCookie_req.ctxcsn, &syncCookie.ctxcsn,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
793
						&text );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
794
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
795
				if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
Kurt Zeilenga's avatar
Kurt Zeilenga committed
796
797
					match < 0 && err == LDAP_SUCCESS )
				{
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
798
					syncrepl_updateCookie( si, op, psub, &syncCookie );
799
800
801
802
803
				}
				if ( rctrls ) {
					ldap_controls_free( rctrls );
				}
				if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
804
					/* FIXME : different error behaviors according to
805
806
807
					 *	1) err code : LDAP_BUSY ...
					 *	2) on err policy : stop service, stop sync, retry
					 */
808
					if ( refreshDeletes == 0 && match < 0 &&
Kurt Zeilenga's avatar
Kurt Zeilenga committed
809
810
						err == LDAP_SUCCESS )
					{
811
						syncrepl_del_nonpresent( op, si, NULL );
812
813
814
					} else {
						avl_free( si->si_presentlist, avl_ber_bvfree );
						si->si_presentlist = NULL;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
815
					}
816
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
817
818
819
820
821
822
823
				if ( err == LDAP_SUCCESS
					&& si->si_logstate == SYNCLOG_FALLBACK ) {
					si->si_logstate = SYNCLOG_LOGGING;
					rc = LDAP_SYNC_REFRESH_REQUIRED;
				} else {
					rc = -2;
				}
824
				goto done;
825
826
				break;

827
			case LDAP_RES_INTERMEDIATE:
828
				rc = ldap_parse_intermediate( si->si_ld, msg,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
829
830
					&retoid, &retdata, NULL, 0 );
				if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
831
					ber_init2( ber, retdata, LBER_USE_DER );
832

833
834
835
					switch ( si_tag = ber_peek_tag( ber, &len )) {
					ber_tag_t tag;
					case LDAP_TAG_SYNC_NEW_COOKIE:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
836
837
838
839
						Debug( LDAP_DEBUG_SYNC,
							"do_syncrep2: %s - %s%s\n", 
							"LDAP_RES_INTERMEDIATE", 
							"NEW_COOKIE", "\n" );
840
841
842
843
						ber_scanf( ber, "tm", &tag, &cookie );
						break;
					case LDAP_TAG_SYNC_REFRESH_DELETE:
					case LDAP_TAG_SYNC_REFRESH_PRESENT:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
844
845
846
847
848
849
						Debug( LDAP_DEBUG_SYNC,
							"do_syncrep2: %s - %s%s\n", 
							"LDAP_RES_INTERMEDIATE", 
							si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ?
							"REFRESH_PRESENT" : "REFRESH_DELETE",
							"\n" );
Howard Chu's avatar
Howard Chu committed
850
						if ( si_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
Howard Chu's avatar
Howard Chu committed
851
852
853
854
							si->si_refreshDelete = 1;
						} else {
							si->si_refreshPresent = 1;
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
855
						ber_scanf( ber, "t{" /*"}"*/, &tag );
856
857
						if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
						{
858
							ber_scanf( ber, "m", &cookie );
859
							if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
860
861
								ch_free( syncCookie.octet_str.bv_val );
								ber_dupbv( &syncCookie.octet_str, &cookie );
862
							}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
863
							if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
864
							{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
865
								slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
866
							}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
867
						}
868
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
869
							LDAP_TAG_REFRESHDONE )
870
871
872
						{
							ber_scanf( ber, "b", &refreshDone );
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
873
						ber_scanf( ber, /*"{"*/ "}" );
874
875
						break;
					case LDAP_TAG_SYNC_ID_SET:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
876
877
878
879
880
						Debug( LDAP_DEBUG_SYNC,
							"do_syncrep2: %s - %s%s\n", 
							"LDAP_RES_INTERMEDIATE", 
							"SYNC_ID_SET",
							"\n" );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
881
						ber_scanf( ber, "t{" /*"}"*/, &tag );
882
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
883
884
							LDAP_TAG_SYNC_COOKIE )
						{
885
							ber_scanf( ber, "m", &cookie );
886
							if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
887
888
								ch_free( syncCookie.octet_str.bv_val );
								ber_dupbv( &syncCookie.octet_str, &cookie );
889
							}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
890
							if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
891
							{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
892
								slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
893
							}
894
895
						}
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
896
							LDAP_TAG_REFRESHDELETES )
897
898
899
900
						{
							ber_scanf( ber, "b", &refreshDeletes );
						}
						ber_scanf( ber, "[W]", &syncUUIDs );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
901
						ber_scanf( ber, /*"{"*/ "}" );
902
903
904
905
906
907
908
909
910
911
912
913
914
						if ( refreshDeletes ) {
							syncrepl_del_nonpresent( op, si, syncUUIDs );
							ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
						} else {
							for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
								struct berval *syncuuid_bv;
								syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] );
								slap_sl_free( syncUUIDs[i].bv_val,op->o_tmpmemctx );
								avl_insert( &si->si_presentlist,
									(caddr_t) syncuuid_bv,
									syncuuid_cmp, avl_dup_error );
							}
							slap_sl_free( syncUUIDs, op->o_tmpmemctx );
915
						}
916
917
						break;
					default:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
918
919
						Debug( LDAP_DEBUG_ANY,
							"do_syncrep2 : unknown syncinfo tag (%ld)\n",
920
						(long) si_tag, 0, 0 );
921
922
923
						ldap_memfree( retoid );
						ber_bvfree( retdata );
						continue;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
924
925
					}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
926
					if ( BER_BVISNULL( &syncCookie_req.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
927
						match = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
928
					} else if ( BER_BVISNULL( &syncCookie.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
929
930
931
932
933
						match = 1;
					} else {
						value_match( &match, slap_schema.si_ad_entryCSN,
							slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
							SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
934
935
							&syncCookie_req.ctxcsn,
							&syncCookie.ctxcsn, &text );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
936
					}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
937

Kurt Zeilenga's avatar
Kurt Zeilenga committed
938
					if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
Kurt Zeilenga's avatar
Kurt Zeilenga committed
939
940
						match < 0 )
					{
941
						syncrepl_updateCookie( si, op, psub, &syncCookie);
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
942
943
					}

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
944
					if ( si->si_refreshPresent == 1 ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
945
						if ( match < 0 ) {
946
							syncrepl_del_nonpresent( op, si, NULL );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
947
						}
948
					} 
949
950
951
952

					ldap_memfree( retoid );
					ber_bvfree( retdata );
					break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
953

954
				} else {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
955
					Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
956
957
						"unknown intermediate response (%d)\n",
						rc, 0, 0 );
958
959
960
961
962
					ldap_memfree( retoid );
					ber_bvfree( retdata );
					break;
				}
				break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
963

964
			default:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
965
				Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
966
967
968
969
					"unknown message\n", 0, 0, 0 );
				break;

			}