1 /* ldapsync.c -- LDAP Content Sync Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2004 The OpenLDAP Foundation.
6 * Portions Copyright 2003 IBM Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
22 #include <ac/string.h>
23 #include <ac/socket.h>
27 #include "../../libraries/liblber/lber-int.h" /* get ber_strndup() */
28 #include "lutil_ldap.h"
31 struct sync_cookie *slap_sync_cookie = NULL;
33 struct slap_sync_cookie_s slap_sync_cookie =
34 LDAP_STAILQ_HEAD_INITIALIZER( slap_sync_cookie );
38 slap_build_sync_state_ctrl(
46 struct berval *cookie)
51 const char *text = NULL;
53 BerElementBuffer berbuf;
54 BerElement *ber = (BerElement *)&berbuf;
56 struct berval entryuuid_bv = BER_BVNULL;
58 ber_init2( ber, 0, LBER_USE_DER );
59 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
61 ctrls[num_ctrls] = slap_sl_malloc ( sizeof ( LDAPControl ), op->o_tmpmemctx );
63 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
64 AttributeDescription *desc = a->a_desc;
65 if ( desc == slap_schema.si_ad_entryUUID ) {
66 ber_dupbv( &entryuuid_bv, &a->a_nvals[0] );
70 if ( send_cookie && cookie ) {
71 ber_printf( ber, "{eOON}",
72 entry_sync_state, &entryuuid_bv, cookie );
74 ber_printf( ber, "{eON}",
75 entry_sync_state, &entryuuid_bv );
78 ch_free( entryuuid_bv.bv_val );
79 entryuuid_bv.bv_val = NULL;
81 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
82 ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
83 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
88 Debug( LDAP_DEBUG_TRACE,
89 "slap_build_sync_ctrl: ber_flatten2 failed\n",
91 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
99 slap_build_sync_done_ctrl(
105 struct berval *cookie,
109 BerElementBuffer berbuf;
110 BerElement *ber = (BerElement *)&berbuf;
112 ber_init2( ber, NULL, LBER_USE_DER );
113 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
115 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
117 ber_printf( ber, "{" );
118 if ( send_cookie && cookie ) {
119 ber_printf( ber, "O", cookie );
121 if ( refreshDeletes == LDAP_SYNC_REFRESH_DELETES ) {
122 ber_printf( ber, "b", refreshDeletes );
124 ber_printf( ber, "N}" );
126 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
127 ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
128 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
133 Debug( LDAP_DEBUG_TRACE,
134 "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
136 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
145 slap_build_sync_state_ctrl_from_slog(
148 struct slog_entry *slog_e,
149 int entry_sync_state,
153 struct berval *cookie)
158 const char *text = NULL;
160 BerElementBuffer berbuf;
161 BerElement *ber = (BerElement *)&berbuf;
163 struct berval entryuuid_bv = BER_BVNULL;
165 ber_init2( ber, NULL, LBER_USE_DER );
166 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
168 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
170 ber_dupbv( &entryuuid_bv, &slog_e->sl_uuid );
172 if ( send_cookie && cookie ) {
173 ber_printf( ber, "{eOON}",
174 entry_sync_state, &entryuuid_bv, cookie );
176 ber_printf( ber, "{eON}",
177 entry_sync_state, &entryuuid_bv );
180 ch_free( entryuuid_bv.bv_val );
181 entryuuid_bv.bv_val = NULL;
183 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
184 ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
185 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
190 Debug( LDAP_DEBUG_TRACE,
191 "slap_build_sync_ctrl: ber_flatten2 failed\n",
193 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
205 struct berval *cookie,
210 BerElementBuffer berbuf;
211 BerElement *ber = (BerElement *)&berbuf;
212 struct berval rspdata;
216 ber_init2( ber, NULL, LBER_USE_DER );
217 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
221 case LDAP_TAG_SYNC_NEW_COOKIE:
222 ber_printf( ber, "tO", type, cookie );
224 case LDAP_TAG_SYNC_REFRESH_DELETE:
225 case LDAP_TAG_SYNC_REFRESH_PRESENT:
226 ber_printf( ber, "t{", type );
228 ber_printf( ber, "O", cookie );
230 if ( refreshDone == 0 ) {
231 ber_printf( ber, "b", refreshDone );
233 ber_printf( ber, "N}" );
235 case LDAP_TAG_SYNC_ID_SET:
236 ber_printf( ber, "t{", type );
238 ber_printf( ber, "O", cookie );
240 if ( refreshDeletes == 1 ) {
241 ber_printf( ber, "b", refreshDeletes );
243 ber_printf( ber, "[W]", syncUUIDs );
244 ber_printf( ber, "N}" );
247 Debug( LDAP_DEBUG_TRACE,
248 "slap_send_syncinfo: invalid syncinfo type (%d)\n",
254 ret = ber_flatten2( ber, &rspdata, 0 );
257 Debug( LDAP_DEBUG_TRACE,
258 "slap_send_syncinfo: ber_flatten2 failed\n",
260 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
264 rs->sr_rspdata = &rspdata;
265 send_ldap_intermediate( op, rs );
266 rs->sr_rspdata = NULL;
273 slap_compose_sync_cookie(
275 struct berval *cookie,
280 char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 20 ];
282 if ( csn->bv_val == NULL ) {
287 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
292 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
295 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
296 "sid=%03d,rid=%03d", sid, rid );
302 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
303 "csn=%s", csn->bv_val );
305 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
306 "csn=%s,rid=%03d", csn->bv_val, rid );
310 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
311 "csn=%s,sid=%03d", csn->bv_val, sid );
313 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
314 "csn=%s,sid=%03d,rid=%03d", csn->bv_val, sid, rid );
318 ber_str2bv( cookiestr, strlen(cookiestr), 1, cookie );
322 slap_sync_cookie_free(
323 struct sync_cookie *cookie,
327 if ( cookie == NULL )
330 if ( cookie->ctxcsn ) {
331 ber_bvarray_free( cookie->ctxcsn );
332 cookie->ctxcsn = NULL;
335 if ( cookie->octet_str ) {
336 ber_bvarray_free( cookie->octet_str );
337 cookie->octet_str = NULL;
348 slap_parse_sync_cookie(
349 struct sync_cookie *cookie
360 struct berval *ctxcsn;
362 if ( cookie == NULL )
365 if (( csn_ptr = strstr( cookie->octet_str[0].bv_val, "csn=" )) != NULL ) {
366 csn_str = SLAP_STRNDUP( csn_ptr, LDAP_LUTIL_CSNSTR_BUFSIZE );
367 if ( (cval = strchr( csn_str, ',' )) != NULL ) {
369 csn_str_len = cval - csn_str - (sizeof("csn=") - 1);
371 csn_str_len = cookie->octet_str[0].bv_len -
372 (csn_ptr - cookie->octet_str[0].bv_val) -
373 (sizeof("csn=") - 1);
375 ctxcsn = ber_str2bv( csn_str + (sizeof("csn=")-1),
376 csn_str_len, 1, NULL );
378 ber_bvarray_add( &cookie->ctxcsn, ctxcsn );
381 cookie->ctxcsn = NULL;
384 if (( sid_ptr = strstr( cookie->octet_str->bv_val, "sid=" )) != NULL ) {
385 sid_str = SLAP_STRNDUP( sid_ptr,
386 SLAP_SYNC_SID_SIZE + sizeof("sid=") - 1 );
387 if ( (cval = strchr( sid_str, ',' )) != NULL ) {
390 cookie->sid = atoi( sid_str + sizeof("sid=") - 1 );
396 if (( rid_ptr = strstr( cookie->octet_str->bv_val, "rid=" )) != NULL ) {
397 rid_str = SLAP_STRNDUP( rid_ptr,
398 SLAP_SYNC_RID_SIZE + sizeof("rid=") - 1 );
399 if ( (cval = strchr( rid_str, ',' )) != NULL ) {
402 cookie->rid = atoi( rid_str + sizeof("rid=") - 1 );
411 slap_init_sync_cookie_ctxcsn(
412 struct sync_cookie *cookie
415 char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE + 4 ];
416 struct berval octet_str = BER_BVNULL;
417 struct berval ctxcsn = BER_BVNULL;
418 struct berval ctxcsn_dup = BER_BVNULL;
419 struct berval slap_syncCookie;
421 if ( cookie == NULL )
424 octet_str.bv_len = snprintf( csnbuf, LDAP_LUTIL_CSNSTR_BUFSIZE + 4,
425 "csn=%4d%02d%02d%02d%02d%02dZ#%06x#%02x#%06x",
426 1900, 1, 1, 0, 0, 0, 0, 0, 0 );
427 octet_str.bv_val = csnbuf;
428 build_new_dn( &slap_syncCookie, &cookie->octet_str[0], &octet_str, NULL );
429 ber_bvarray_free( cookie->octet_str );
430 cookie->octet_str = NULL;
431 ber_bvarray_add( &cookie->octet_str, &slap_syncCookie );
433 ber_dupbv( &ctxcsn, &octet_str );
436 ber_dupbv( &ctxcsn_dup, &ctxcsn );
437 ch_free( ctxcsn.bv_val );
438 ber_bvarray_add( &cookie->ctxcsn, &ctxcsn_dup );
444 slap_dup_sync_cookie(
445 struct sync_cookie *dst,
446 struct sync_cookie *src
450 struct sync_cookie *new;
451 struct berval tmp_bv;
457 ber_bvarray_free( dst->ctxcsn );
458 ber_bvarray_free( dst->octet_str );
461 new = ( struct sync_cookie * )
462 ch_calloc( 1, sizeof( struct sync_cookie ));
469 for ( i=0; src->ctxcsn[i].bv_val; i++ ) {
470 ber_dupbv( &tmp_bv, &src->ctxcsn[i] );
471 ber_bvarray_add( &new->ctxcsn, &tmp_bv );
475 if ( src->octet_str ) {
476 for ( i=0; src->octet_str[i].bv_val; i++ ) {
477 ber_dupbv( &tmp_bv, &src->octet_str[i] );
478 ber_bvarray_add( &new->octet_str, &tmp_bv );
486 slap_build_syncUUID_set(
495 struct berval entryuuid_bv = BER_BVNULL;
497 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
498 AttributeDescription *desc = a->a_desc;
499 if ( desc == slap_schema.si_ad_entryUUID ) {
500 ber_dupbv_x( &entryuuid_bv, &a->a_nvals[0], op->o_tmpmemctx );
504 ret = ber_bvarray_add_x( set, &entryuuid_bv, op->o_tmpmemctx );