* " sp/<cint>/<cookie>/<slimit>\n"
* */
#endif
+#ifdef LDAP_SYNC
+" [!]sync= ro[/<cookie>] (ldap sync - refreshOnly)\n"
+" rp[/<cookie>][/<slimit>] (ldap sync - refreshAndPersist)\n"
+#endif
" -F prefix URL prefix for files (default: %s)\n"
" -l limit time limit (in seconds) for search\n"
" -L print responses in LDIFv1 format\n"
static int subentries = 0, valuesReturnFilter = 0;
static char *vrFilter = NULL;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
static int lcup = 0;
+static int ldapsync = 0;
+#endif
+
+#ifdef LDAP_CLIENT_UPDATE
static int lcup_cint = 0;
static struct berval lcup_cookie = { 0, NULL };
-static int lcup_slimit = 0;
+static int lcup_slimit = -1;
+#endif
+
+#ifdef LDAP_SYNC
+static struct berval sync_cookie = { 0, NULL };
+static int sync_slimit = -1;
#endif
static int pagedResults = 0;
#endif
#ifdef LDAP_CLIENT_UPDATE
- } else if ( strcasecmp( control, "lcup" ) == 0 ) {
- char *cookiep;
- char *slimitp;
- if ( lcup ) {
- fprintf( stderr, "client update control previously specified\n");
- exit( EXIT_FAILURE );
- }
- if ( cvalue == NULL ) {
- fprintf( stderr,
- "missing specification of client update control\n");
- exit( EXIT_FAILURE );
- }
- if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
- lcup = LDAP_CUP_PERSIST_ONLY;
- cvalue += 2;
- cookiep = strchr( cvalue, '/' );
- *cookiep++ = '\0';
- lcup_cint = atoi( cvalue );
- cvalue = cookiep;
- slimitp = strchr( cvalue, '/' );
- *slimitp++ = '\0';
- ber_str2bv( cookiep, 0, 0, &lcup_cookie );
- lcup_slimit = atoi( slimitp );
+ } else if ( strcasecmp( control, "lcup" ) == 0 ) {
+ char *cookiep;
+ char *slimitp;
+ if ( lcup ) {
+ fprintf( stderr, "client update control previously specified\n");
+ exit( EXIT_FAILURE );
+ }
+ if ( ldapsync != -1 ) {
+ fprintf( stderr, "ldap sync control previously specified\n");
+ exit( EXIT_FAILURE );
+ }
+ if ( cvalue == NULL ) {
+ fprintf( stderr,
+ "missing specification of client update control\n");
+ exit( EXIT_FAILURE );
+ }
+ if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
+ lcup = LDAP_CUP_PERSIST_ONLY;
+ cvalue = strchr( cvalue, '/' );
+ cvalue++;
+ cookiep = strchr( cvalue, '/' );
+ *cookiep++ = '\0';
+ lcup_cint = atoi( cvalue );
+ cvalue = cookiep;
+ slimitp = strchr( cvalue, '/' );
+ *slimitp++ = '\0';
+ while ( isspace( *cookiep ) ) cookiep++;
+ ber_str2bv( cookiep, 0, 0, &lcup_cookie );
+ lcup_slimit = atoi( slimitp );
/*
} else if ( strncasecmp( cvalue, "s", 1 ) == 0 ) {
lcup = LDAP_CUP_SYNC_ONLY;
if ( crit ) lcup *= -1;
#endif
+#ifdef LDAP_SYNC
+ } else if ( strcasecmp( control, "sync" ) == 0 ) {
+ char *cookiep;
+ char *slimitp;
+ if ( ldapsync ) {
+ fprintf( stderr, "ldap sync control previously specified\n" );
+ exit( EXIT_FAILURE );
+ }
+ if ( lcup ) {
+ fprintf( stderr, "client update control previously specified\n" );
+ exit( EXIT_FAILURE );
+ }
+ if ( cvalue == NULL ) {
+ fprintf( stderr,
+ "missing specification of ldap sync control\n");
+ exit( EXIT_FAILURE );
+ }
+ if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
+ ldapsync = LDAP_SYNC_REFRESH_ONLY;
+ cookiep = strchr( cvalue, '/' );
+ if ( cookiep != NULL ) {
+ cookiep++;
+ if ( *cookiep != '\0' ) {
+ ber_str2bv( cookiep, 0, 0, &sync_cookie );
+ }
+ }
+ } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
+ ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
+ cookiep = strchr( cvalue, '/' );
+ if ( cookiep != NULL ) {
+ *cookiep++ = '\0';
+ cvalue = cookiep;
+ }
+ slimitp = strchr( cvalue, '/' );
+ if ( slimitp != NULL ) {
+ *slimitp++ = '\0';
+ }
+ if ( cookiep != NULL && *cookiep != '\0' )
+ ber_str2bv( cookiep, 0, 0, &sync_cookie );
+ if ( slimitp != NULL && *slimitp != '\0' )
+ sync_slimit = atoi( slimitp );
+ } else {
+ fprintf( stderr,
+ "ldap sync control value \"%s\" invalid\n",
+ cvalue );
+ exit( EXIT_FAILURE );
+ }
+ if ( crit ) ldapsync *= -1;
+#endif
+
} else {
fprintf( stderr, "Invalid control name: %s\n", control );
usage();
struct berval *cubvalp = NULL;
#endif
+#ifdef LDAP_SYNC
+ BerElement *syncber = NULL;
+ struct berval *syncbvalp = NULL;
+#endif
+
npagedresponses = npagedentries = npagedreferences =
npagedextended = npagedpartial = 0;
|| valuesReturnFilter || pageSize
#ifdef LDAP_CLIENT_UPDATE
|| lcup
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+ || ldapsync
+#endif
) {
int err;
int i=0;
#endif
#ifdef LDAP_CLIENT_UPDATE
- if ( lcup ) {
- if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ if ( lcup ) {
+ if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ return EXIT_FAILURE;
+ }
+
+ if ( lcup_cookie.bv_len == 0 ) {
+ err = ber_printf( cuber, "{ei}", abs(lcup), lcup_cint );
+ } else {
+ err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
+ LDAP_LCUP_COOKIE_OID, &lcup_cookie );
+ }
+
+ if ( err == LBER_ERROR ) {
+ ber_free( cuber, 1 );
+ fprintf( stderr, "client update control encoding error!\n" );
+ return EXIT_FAILURE;
+ }
+
+ if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
+ return EXIT_FAILURE;
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
+ c[i].ldctl_value = (*cubvalp);
+ c[i].ldctl_iscritical = lcup < 0;
+ i++;
+ }
+#endif
+
+#ifdef LDAP_SYNC
+ if ( ldapsync ) {
+ if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
}
- err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
- LDAP_CLIENT_UPDATE_COOKIE, &lcup_cookie);
+
+ if ( sync_cookie.bv_len == 0 ) {
+ err = ber_printf( syncber, "{e}", abs(ldapsync) );
+ } else {
+ err = ber_printf( syncber, "{eO}", abs(ldapsync),
+ &sync_cookie );
+ }
+
if ( err == LBER_ERROR ) {
- ber_free( cuber, 1 );
- fprintf( stderr, "client update control encoding error!\n" );
+ ber_free( syncber, 1 );
+ fprintf( stderr, "ldap sync control encoding error!\n" );
return EXIT_FAILURE;
}
- if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
+ if ( ber_flatten( syncber, &syncbvalp ) == LBER_ERROR ) {
return EXIT_FAILURE;
}
- c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
- c[i].ldctl_value=(*cubvalp);
- c[i].ldctl_iscritical = lcup < 0;
+ c[i].ldctl_oid = LDAP_CONTROL_SYNC;
+ c[i].ldctl_value = (*syncbvalp);
+ c[i].ldctl_iscritical = ldapsync < 0;
i++;
}
#endif
int nextended;
int npartial;
LDAPMessage *res, *msg;
- ber_int_t msgid;
+ ber_int_t msgid;
+#ifdef LDAP_SYNC
+ char *retoid = NULL;
+ struct berval *retdata = NULL;
+ int nresponses_psearch = -1;
+ int cancel_msgid = -1;
+#endif
if( filtpatt != NULL ) {
filter = malloc( strlen( filtpatt ) + strlen( value ) );
rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
sctrls, cctrls, timeout, sizelimit, &msgid );
+ printf("msgid = %d\n", msgid);
+
if ( filtpatt != NULL ) {
free( filter );
}
msg != NULL;
msg = ldap_next_message( ld, msg ) )
{
- if( nresponses++ ) putchar('\n');
+ if ( nresponses++ ) putchar('\n');
+#if LDAP_SYNC
+ if ( nresponses_psearch >= 0 )
+ nresponses_psearch++;
+#endif
switch( ldap_msgtype( msg ) ) {
case LDAP_RES_SEARCH_ENTRY:
/* unsolicited extended operation */
goto done;
}
+
+#ifdef LDAP_SYNC
+ if ( cancel_msgid != -1 &&
+ cancel_msgid == ldap_msgid( msg ) ) {
+ printf("Cancelled \n");
+ printf("cancel_msgid = %d\n", cancel_msgid);
+ goto done;
+ }
+#endif
+
break;
case LDAP_RES_EXTENDED_PARTIAL:
if ( pageSize != 0 ) {
rc = parse_page_control( ld, msg, &cookie );
}
+
+#ifdef LDAP_CLIENT_UPDATE
+ if ( lcup == LDAP_CUP_PERSIST_ONLY ||
+ lcup == LDAP_CUP_SYNC_AND_PERSIST ) {
+ break;
+ }
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
+ break;
+ }
+#endif
+
goto done;
+
+#ifdef LDAP_SYNC
+ case LDAP_RES_INTERMEDIATE_RESP:
+ ldap_parse_intermediate_resp_result( ld, msg, &retoid, &retdata, 0 );
+ nresponses_psearch = 0;
+
+ if ( strcmp( retoid, LDAP_SYNC_INFO ) ) {
+ printf("Unexpected Intermediate Response\n");
+ ldap_memfree( retoid );
+ ber_bvfree( retdata );
+ goto done;
+ } else {
+ printf("SyncInfo Received\n");
+ ldap_memfree( retoid );
+ ber_bvfree( retdata );
+ break;
+ }
+#endif
}
+
#ifdef LDAP_CLIENT_UPDATE
- if ( nresponses >= lcup_slimit ) {
+ if ( lcup && lcup_slimit != -1 && nresponses >= lcup_slimit ) {
ldap_abandon (ld, ldap_msgid(msg));
goto done;
}
#endif
+#ifdef LDAP_SYNC
+ if ( ldapsync && sync_slimit != -1 &&
+ nresponses_psearch >= sync_slimit ) {
+ BerElement *msgidber = NULL;
+ struct berval *msgidvalp = NULL;
+ msgidber = ber_alloc_t(LBER_USE_DER);
+ ber_printf(msgidber, "{i}", msgid);
+ ber_flatten(msgidber, &msgidvalp);
+ ldap_extended_operation(ld, LDAP_EXOP_X_CANCEL,
+ msgidvalp, NULL, NULL, &cancel_msgid);
+ nresponses_psearch = -1;
+ }
+#endif
}
/*
#define LDAP_CLIENT_UPDATE 1
+#define LDAP_SYNC 2
*/
+
#ifdef LDAP_CLIENT_UPDATE
#define LDAP_CONTROL_CLIENT_UPDATE "1.3.6.1.4.1.4203.666.5.3"
#define LDAP_CONTROL_ENTRY_UPDATE "1.3.6.1.4.1.4203.666.5.4"
-#define LDAP_CONTROL_CLIENT_UPDATE_DONE "1.3.6.1.4.1.4203.666.5.5"
+#define LDAP_CONTROL_CLIENT_UPDATE_DONE "1.3.6.1.4.1.4203.666.5.5"
+#define LDAP_LCUP_COOKIE_OID "1.3.6.1.4.1.4203.666.10.1"
+#endif
+
+#ifdef LDAP_SYNC
+#define LDAP_CONTROL_SYNC "1.3.6.1.4.1.4203.666.5.TBD1"
+#define LDAP_CONTROL_SYNC_STATE "1.3.6.1.4.1.4203.666.5.TBD2"
+#define LDAP_CONTROL_SYNC_DONE "1.3.6.1.4.1.4203.666.5.TBD3"
+#define LDAP_SYNC_INFO "1.3.6.1.4.1.4203.666.5.TBD4"
+
+#define LDAP_SYNC_REFRESH_DONE 0
+#define LDAP_SYNC_NEW_COOKIE 1
+
+#define LDAP_SYNC_PRESENT 0
+#define LDAP_SYNC_ADD 1
+#define LDAP_SYNC_MODIFY 2
+#define LDAP_SYNC_DELETE 3
#endif
#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473"
#define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octet string */
#ifdef LDAP_CLIENT_UPDATE
-#define LDAP_TAG_COOKIE ((ber_tag_t) 0x30U) /* sequence */
-#endif /* LDAP_CLIENT_UPDATE */
+#define LDAP_LCUP_TAG_COOKIE ((ber_tag_t) 0x30U) /* sequence */
+#endif
+
+#ifdef LDAP_SYNC
+#define LDAP_SYNC_TAG_COOKIE ((ber_tag_t) 0x04U) /* octet string */
+#endif
#define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */
#define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */
#define LDAP_CUP_UNSUPPORTED_SCHEME 0x65
#define LDAP_CUP_CLIENT_DISCONNECT 0x66
#define LDAP_CUP_RELOAD_REQUIRED 0x67
-
-/* LCUP update type */
-#define LDAP_CUP_SYNC_ONLY 0x00
-#define LDAP_CUP_SYNC_AND_PERSIST 0x01
-#define LDAP_CUP_PERSIST_ONLY 0x02
-
-/* LCUP default cookie interval */
-#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
/* resultCode for Cancel Response */
#define LDAP_CANCELLED 0x68
#define LDAP_CANCEL_ACK 0x02
#define LDAP_CANCEL_DONE 0x03
+#ifdef LDAP_CLIENT_UPDATE
+/* LCUP update type */
+#define LDAP_CUP_NONE 0x00
+#define LDAP_CUP_SYNC_ONLY 0x01
+#define LDAP_CUP_PERSIST_ONLY 0x02
+#define LDAP_CUP_SYNC_AND_PERSIST 0x03
+
+/* LCUP default cookie interval */
+#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01
+#endif /* LDAP_CLIENT_UPDATE */
+
+/* LDAP SYNC request type */
+#ifdef LDAP_SYNC
+#define LDAP_SYNC_NONE 0x00
+#define LDAP_SYNC_REFRESH_ONLY 0x01
+#define LDAP_SYNC_REFRESH_AND_PERSIST 0x03
+#endif
+
/*
* This structure represents both ldap messages and ldap responses.
* These are really the same, except in the case of search responses,
{LDAP_MORE_RESULTS_TO_RETURN, "More results to return" },
{LDAP_CLIENT_LOOP, "Client Loop" },
{LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral Limit Exceeded" },
+#ifdef LDAP_CLIENT_UPDATE
+ {LDAP_CUP_RESOURCES_EXHAUSTED, "LDAP Client Update Resource Exhausted" },
+ {LDAP_CUP_SECURITY_VIOLATION, "LDAP Client Update Security Violation" },
+ {LDAP_CUP_INVALID_COOKIE, "LDAP Client Update Invalid Cookie" },
+ {LDAP_CUP_UNSUPPORTED_SCHEME, "LDAP Client Update Unsupported Scheme" },
+ {LDAP_CUP_CLIENT_DISCONNECT, "LDAP Client Update Client Disconnect" },
+ {LDAP_CUP_RELOAD_REQUIRED, "LDAP Client Update Reload Required" },
+#endif
+ {LDAP_CANCELLED, "LDAP Cancelled" },
+ {LDAP_NO_SUCH_OPERATION, "LDAP No Operation to Cancel" },
+ {LDAP_TOO_LATE, "LDAP Too Late to Cancel" },
+ {LDAP_CANNOT_CANCEL, "LDAP Cannot Cancel" },
{-1, NULL}
};
done:
-#if LDAP_CLIENT_UPDATE
+#ifdef LDAP_CLIENT_UPDATE
for ( i = 0; i < nbackends; i++ ) {
if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue;
if ( bdb_abandon( &backends[i], conn, id ) == LDAP_SUCCESS ) {
#endif
int noop = 0;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
#endif
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !noop ) {
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_ADD );
+ bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_ADD );
}
}
#endif /* LDAP_CLIENT_UPDATE */
ID bi_lastid;
ldap_pvt_thread_mutex_t bi_lastid_mutex;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
LDAP_LIST_HEAD(pl, slap_op) psearch_list;
#endif
#ifdef SLAP_IDL_CACHE
int noop = 0;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
#endif
return_results:
send_ldap_result( conn, op, rc, NULL, text, NULL, NULL );
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !noop ) {
LDAP_LIST_FOREACH( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_DELETE );
+ bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_DELETE );
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
if(rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
bdb->bi_search_stack = NULL;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
LDAP_LIST_INIT (&bdb->psearch_list);
#endif
#include "idl.h"
#include "external.h"
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+
+#define IS_BDB_REPLACE (( psearch_type == LDAP_PSEARCH_BY_DELETE ) || \
+ ( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT ))
+#define IS_BDB_LCUP_REPLACE (( protocol == LDAP_CLIENT_UPDATE ) && IS_BDB_REPLACE )
static int psearch_base_candidate(
BackendDB *be,
- Entry *e,
+ Entry *e,
ID *ids );
+
static int psearch_candidates(
- BackendDB *be,
- Operation *op,
- Entry *e,
- Filter *filter,
- int scope,
- int deref,
- ID *ids );
+ BackendDB *be,
+ Operation *op,
+ Entry *e,
+ Filter *filter,
+ int scope,
+ int deref,
+ ID *ids );
int
bdb_abandon(
return LDAP_UNAVAILABLE;
}
+int
+bdb_cancel(
+ BackendDB *be,
+ Connection *conn,
+ ber_int_t id )
+{
+ Operation *ps_list;
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+
+ LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
+ if ( ps_list->o_connid == conn->c_connid ) {
+ if ( ps_list->o_msgid == id ) {
+ ps_list->o_cancel = LDAP_CANCEL_DONE;
+ LDAP_LIST_REMOVE( ps_list, link );
+
+#if 0
+ bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls, 1, &latest_entrycsn_bv );
+ send_search_result( conn, ps_list, LDAP_CANCELLED,
+ NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries);
+#endif
+ send_search_result( conn, ps_list, LDAP_CANCELLED,
+ NULL, NULL, NULL, NULL, 0);
+
+
+
+ slap_op_free ( ps_list );
+ return LDAP_SUCCESS;
+ }
+ }
+ }
+ return LDAP_UNAVAILABLE;
+}
+
int
bdb_add_psearch_spec(
BackendDB *be,
Filter *filter,
struct berval *fstr,
AttributeName *attrs,
- int attrsonly )
+ int attrsonly,
+ int protocol )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- LDAP_LIST_FIRST(&op->psearch_spec) = (struct lcup_search_spec *)
- calloc ( 1, sizeof ( struct lcup_search_spec ) );
+ LDAP_LIST_FIRST( &op->psearch_spec ) = (struct ldap_psearch_spec *)
+ calloc ( 1, sizeof ( struct ldap_psearch_spec ) );
- LDAP_LIST_FIRST(&op->psearch_spec)->op = op;
+ LDAP_LIST_FIRST( &op->psearch_spec )->op = op;
- LDAP_LIST_FIRST(&op->psearch_spec)->base = ber_dupbv(NULL, base);
- LDAP_LIST_FIRST(&op->psearch_spec)->nbase = ber_dupbv(NULL, nbase);
+ LDAP_LIST_FIRST( &op->psearch_spec )->base = ber_dupbv(NULL, base);
+ LDAP_LIST_FIRST( &op->psearch_spec )->nbase = ber_dupbv(NULL, nbase);
- LDAP_LIST_FIRST(&op->psearch_spec)->scope = scope;
- LDAP_LIST_FIRST(&op->psearch_spec)->deref = deref;
- LDAP_LIST_FIRST(&op->psearch_spec)->slimit = slimit;
- LDAP_LIST_FIRST(&op->psearch_spec)->tlimit = tlimit;
+ LDAP_LIST_FIRST( &op->psearch_spec )->scope = scope;
+ LDAP_LIST_FIRST( &op->psearch_spec )->deref = deref;
+ LDAP_LIST_FIRST( &op->psearch_spec )->slimit = slimit;
+ LDAP_LIST_FIRST( &op->psearch_spec )->tlimit = tlimit;
- LDAP_LIST_FIRST(&op->psearch_spec)->filter = filter;
- LDAP_LIST_FIRST(&op->psearch_spec)->filterstr = ber_dupbv(NULL, fstr);
- LDAP_LIST_FIRST(&op->psearch_spec)->attrs = attrs;
+ LDAP_LIST_FIRST( &op->psearch_spec )->filter = filter;
+ LDAP_LIST_FIRST( &op->psearch_spec )->filterstr = ber_dupbv(NULL, fstr);
+ LDAP_LIST_FIRST( &op->psearch_spec )->attrs = attrs;
- LDAP_LIST_FIRST(&op->psearch_spec)->attrsonly = attrsonly;
+ LDAP_LIST_FIRST( &op->psearch_spec )->attrsonly = attrsonly;
- LDAP_LIST_FIRST(&op->psearch_spec)->entry_count = 0;
+ LDAP_LIST_FIRST( &op->psearch_spec )->entry_count = 0;
+
+ LDAP_LIST_FIRST( &op->psearch_spec )->protocol = protocol;
LDAP_LIST_INSERT_HEAD( &bdb->psearch_list, op, link );
}
Operation *op,
Operation *ps_op,
Entry *entry,
- int psearch_type )
+ int psearch_type )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
- const char *text = NULL;
+ const char *text = NULL;
time_t stoptime;
unsigned cursor;
ID id;
ID candidates[BDB_IDL_UM_SIZE];
Entry *e = NULL;
- BerVarray v2refs = NULL;
- Entry *matched = NULL;
+ BerVarray v2refs = NULL;
+ Entry *matched = NULL;
struct berval realbase = { 0, NULL };
int nentries = 0;
int manageDSAit;
- Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
- AttributeAssertion aa_ge, aa_eq;
- struct berval entrycsn_bv = { 0, NULL };
- struct berval latest_entrycsn_bv = { 0, NULL };
+ Filter cookief, csnfnot, csnfeq, csnfand, csnfge;
+ AttributeAssertion aa_ge, aa_eq;
+ struct berval entrycsn_bv = { 0, NULL };
+ struct berval latest_entrycsn_bv = { 0, NULL };
+
+ LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS];
+ int num_ctrls = 0;
struct slap_limits_set *limit = NULL;
int isroot = 0;
DB_LOCK lock;
Connection *ps_conn = ps_op->o_conn;
- struct berval *base = LDAP_LIST_FIRST(&ps_op->psearch_spec)->base;
- struct berval *nbase = LDAP_LIST_FIRST(&ps_op->psearch_spec)->nbase;
- int scope = LDAP_LIST_FIRST(&ps_op->psearch_spec)->scope;
- int deref = LDAP_LIST_FIRST(&ps_op->psearch_spec)->deref;
- int slimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->slimit;
- int tlimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->tlimit;
- Filter *filter = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filter;
- struct berval *filterstr = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filterstr;
- int attrsonly = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrsonly;
+ struct berval *base = LDAP_LIST_FIRST( &ps_op->psearch_spec )->base;
+ struct berval *nbase = LDAP_LIST_FIRST( &ps_op->psearch_spec )->nbase;
+ int scope = LDAP_LIST_FIRST( &ps_op->psearch_spec )->scope;
+ int deref = LDAP_LIST_FIRST( &ps_op->psearch_spec )->deref;
+ int slimit = LDAP_LIST_FIRST( &ps_op->psearch_spec )->slimit;
+ int tlimit = LDAP_LIST_FIRST( &ps_op->psearch_spec )->tlimit;
+ Filter *filter = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filter;
+ struct berval *filterstr = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filterstr;
+ int attrsonly = LDAP_LIST_FIRST( &ps_op->psearch_spec )->attrsonly;
+ int protocol = LDAP_LIST_FIRST( &ps_op->psearch_spec )->protocol;
AttributeName uuid_attr[2];
- AttributeName *attrs = uuid_attr;
-
- if ( psearch_type != LCUP_PSEARCH_BY_DELETE &&
- psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
- {
- attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
- } else {
- attrs[0].an_desc = slap_schema.si_ad_entryUUID;
- attrs[0].an_oc = NULL;
- ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
- attrs[1].an_desc = NULL;
- attrs[1].an_oc = NULL;
- attrs[1].an_name.bv_len = 0;
- attrs[1].an_name.bv_val = NULL;
- }
+ AttributeName *attrs;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
default:
send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
- ch_free( attrs[0].an_name.bv_val );
return rc;
+ }
+
+ for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
+ ctrls[num_ctrls] = NULL;
+ num_ctrls = 0;
+
+ if ( !IS_BDB_REPLACE ) {
+ attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
+ } else {
+#ifdef LDAP_CLIENT_UPDATE
+ if ( protocol == LDAP_CLIENT_UPDATE ) {
+ attrs = uuid_attr;
+ attrs[0].an_desc = slap_schema.si_ad_entryUUID;
+ attrs[0].an_oc = NULL;
+ ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
+ attrs[1].an_desc = NULL;
+ attrs[1].an_oc = NULL;
+ attrs[1].an_name.bv_len = 0;
+ attrs[1].an_name.bv_val = NULL;
+ } else
+#endif
+#ifdef LDAP_SYNC
+ if (protocol == LDAP_SYNC ) {
+ attrs = uuid_attr;
+ attrs[0].an_desc = NULL;
+ attrs[0].an_oc = NULL;
+ attrs[0].an_name.bv_len = 0;
+ attrs[0].an_name.bv_val = NULL;
+ } else
+#endif
+ {
+ rc = 1;
+ goto done;
+ }
}
if ( nbase->bv_len == 0 ) {
send_ldap_result( ps_conn, ps_op, LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
LOCK_ID_FREE( bdb->bi_dbenv, locker );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+ if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
+#endif
return LDAP_BUSY;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
LOCK_ID_FREE( bdb->bi_dbenv, locker );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+ if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
+#endif
return rc;
}
LOCK_ID_FREE( bdb->bi_dbenv, locker );
if ( refs ) ber_bvarray_free( refs );
if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+ if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
+#endif
return rc;
}
LOCK_ID_FREE( bdb->bi_dbenv, locker );
ber_bvarray_free( refs );
ber_memfree( matched_dn.bv_val );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+ if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
+#endif
return 1;
}
}
}
- lcupf.f_choice = LDAP_FILTER_AND;
- lcupf.f_and = &csnfnot;
- lcupf.f_next = NULL;
-
- csnfnot.f_choice = LDAP_FILTER_NOT;
- csnfnot.f_not = &csnfeq;
- csnfnot.f_next = &csnfand;
-
- csnfeq.f_choice = LDAP_FILTER_EQUALITY;
- csnfeq.f_ava = &aa_eq;
- csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
- ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
-
- csnfand.f_choice = LDAP_FILTER_AND;
- csnfand.f_and = &csnfge;
- csnfand.f_next = NULL;
-
- csnfge.f_choice = LDAP_FILTER_GE;
- csnfge.f_ava = &aa_ge;
- csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
- ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
- csnfge.f_next = filter;
+#ifdef LDAP_CLIENT_UPDATE
+ if ( protocol == LDAP_CLIENT_UPDATE ) {
+ cookief.f_choice = LDAP_FILTER_AND;
+ cookief.f_and = &csnfnot;
+ cookief.f_next = NULL;
+
+ csnfnot.f_choice = LDAP_FILTER_NOT;
+ csnfnot.f_not = &csnfeq;
+ csnfnot.f_next = &csnfand;
+
+ csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+ csnfeq.f_ava = &aa_eq;
+ csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
+
+ csnfand.f_choice = LDAP_FILTER_AND;
+ csnfand.f_and = &csnfge;
+ csnfand.f_next = NULL;
+
+ csnfge.f_choice = LDAP_FILTER_GE;
+ csnfge.f_ava = &aa_ge;
+ csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
+ csnfge.f_next = filter;
+ }
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ if ( protocol == LDAP_SYNC ) {
+ cookief.f_choice = LDAP_FILTER_AND;
+ cookief.f_and = &csnfnot;
+ cookief.f_next = NULL;
+
+ csnfnot.f_choice = LDAP_FILTER_NOT;
+ csnfnot.f_not = &csnfeq;
+ csnfnot.f_next = &csnfand;
+
+ csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+ csnfeq.f_ava = &aa_eq;
+ csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfeq.f_av_value, &ps_op->o_sync_state );
+
+ csnfand.f_choice = LDAP_FILTER_AND;
+ csnfand.f_and = &csnfge;
+ csnfand.f_next = NULL;
+
+ csnfge.f_choice = LDAP_FILTER_GE;
+ csnfge.f_ava = &aa_ge;
+ csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfge.f_av_value, &ps_op->o_sync_state );
+ csnfge.f_next = filter;
+ }
+#endif
id = entry->e_id;
goto test_done;
}
- if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
- rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
+ if ( psearch_type != LDAP_PSEARCH_BY_SCOPEOUT ) {
+ rc = test_filter( be, ps_conn, ps_op, e, &cookief );
} else {
rc = LDAP_COMPARE_TRUE;
}
} else
#endif
{
- if ( psearch_type == LCUP_PSEARCH_BY_ADD ||
- psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_MODIFY ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
- {
- Attribute* a;
- int ret;
- int res;
- const char *text = NULL;
- LDAPControl *ctrls[2];
- struct berval *bv;
- char berbuf[LBER_ELEMENT_SIZEOF];
- BerElement *ber = (BerElement *)berbuf;
-
- ber_init2( ber, NULL, LBER_USE_DER );
-
- LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
-
- ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
- ctrls[1] = NULL;
-
- if ( LDAP_LIST_FIRST(
- &ps_op->psearch_spec)->entry_count %
- ps_op->o_clientupdate_interval == 0 )
- {
- /* Send cookie */
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- AttributeDescription *desc = a->a_desc;
- if ( desc == slap_schema.si_ad_entryCSN ) {
- ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
- if ( latest_entrycsn_bv.bv_val == NULL ) {
- ber_dupbv( &latest_entrycsn_bv,
- &entrycsn_bv );
- } else {
- res = value_match( &ret, desc,
- desc->ad_type->sat_ordering,
- SLAP_MR_ASSERTION_SYNTAX_MATCH,
- &entrycsn_bv, &latest_entrycsn_bv,
- &text );
- if ( res != LDAP_SUCCESS ) {
- ret = 0;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: "
- "value_match failed\n",
- 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_search: "
- "value_match failed\n",
- 0, 0, 0 );
-#endif
- }
-
- if ( ret > 0 ) {
- ch_free(latest_entrycsn_bv.bv_val);
- latest_entrycsn_bv.bv_val = NULL;
- ber_dupbv( &latest_entrycsn_bv,
- &entrycsn_bv );
- }
- }
- }
- }
-
- if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
- psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
- {
- ber_printf( ber, "{bb{sON}N}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_FALSE,
- LCUP_COOKIE_OID, &entrycsn_bv );
- } else {
- ber_printf( ber, "{bb{sON}N}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_TRUE,
- LCUP_COOKIE_OID, &entrycsn_bv );
- }
-
- ch_free( entrycsn_bv.bv_val );
- entrycsn_bv.bv_val = NULL;
-
- } else {
- /* Do not send cookie */
- if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
- psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
- {
- ber_printf( ber, "{bbN}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_FALSE );
- } else {
- ber_printf( ber, "{bbN}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_TRUE );
- }
- }
-
- ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
- ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
- ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
-
- if ( ret < 0 ) {
- ber_free_buf( ber );
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: ber_flatten2 failed\n",
- 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_search: ber_flatten2 failed\n",
- 0, 0, 0 );
+#ifdef LDAP_SYNC
+ int premodify_found = 0;
+ int entry_sync_state;
#endif
- send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
- goto done;
- }
-
- result = send_search_entry( be, ps_conn, ps_op,
- e, attrs, attrsonly, ctrls);
-
- ber_free_buf( ber );
- ch_free( ctrls[0] );
- if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
+ if ( psearch_type == LDAP_PSEARCH_BY_ADD ||
+ psearch_type == LDAP_PSEARCH_BY_DELETE ||
+ psearch_type == LDAP_PSEARCH_BY_MODIFY ||
+ psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
+ {
+ if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
struct psid_entry* psid_e;
- LDAP_LIST_FOREACH( psid_e, &op->premodify_list,
- link)
+ LDAP_LIST_FOREACH( psid_e, &op->premodify_list, link)
{
- if( psid_e->ps ==
- LDAP_LIST_FIRST(&ps_op->psearch_spec))
+ if( psid_e->ps == LDAP_LIST_FIRST(&ps_op->psearch_spec))
{
+#ifdef LDAP_SYNC
+ premodify_found = 1;
+#endif
LDAP_LIST_REMOVE(psid_e, link);
break;
}
}
if (psid_e != NULL) free (psid_e);
}
+#ifdef LDAP_SYNC
+ if ( psearch_type == LDAP_PSEARCH_BY_ADD )
+ entry_sync_state = LDAP_SYNC_ADD;
+ else if ( psearch_type == LDAP_PSEARCH_BY_DELETE )
+ entry_sync_state = LDAP_SYNC_DELETE;
+ else if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
+ if ( premodify_found )
+ entry_sync_state = LDAP_SYNC_MODIFY;
+ else
+ entry_sync_state = LDAP_SYNC_ADD;
+ } else if ( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
+ entry_sync_state = LDAP_SYNC_DELETE;
+ else {
+ rc = 1;
+ goto done;
+ }
+#endif
+
+#ifdef LDAP_CLIENT_UPDATE
+ if ( protocol == LDAP_CLIENT_UPDATE ) {
+ int entry_count = ++(LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count);
+ if ( IS_BDB_REPLACE ) {
+ rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
+ num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_TRUE );
+ } else {
+ rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
+ num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
+ }
+ if ( rc != LDAP_SUCCESS )
+ goto done;
+ result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
+ } else
+#endif
+#ifdef LDAP_SYNC
+ if ( protocol == LDAP_SYNC ) {
+ rc = bdb_build_sync_state_ctrl( ps_conn, ps_op, e, entry_sync_state, ctrls,
+ num_ctrls++, 1, &latest_entrycsn_bv );
+ if ( rc != LDAP_SUCCESS )
+ goto done;
+ result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
+ } else
+#endif
+ {
+ rc = 1;
+ goto done;
+ }
- } else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
+ } else if ( psearch_type == LDAP_PSEARCH_BY_PREMODIFY ) {
struct psid_entry* psid_e;
psid_e = (struct psid_entry *) calloc (1,
sizeof(struct psid_entry));
if( v2refs ) ber_bvarray_free( v2refs );
if( realbase.bv_val ) ch_free( realbase.bv_val );
- if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
- psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+ if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
+#endif
return rc;
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
int noop = 0;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
struct psid_entry* pm_list;
struct psid_entry* pm_prev;
"bdb_modify: retrying...\n", 0, 0, 0);
#endif
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
goto done;
}
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !op->o_noop ) {
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY );
+ bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
/* Modify the entry */
rc = bdb_modify_internal( be, conn, op, ltid, modlist, e,
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !op->o_noop ) {
/* Loop through in-scope entries for each psearch spec */
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY );
+ bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
}
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
bdb_psearch(be, conn, op, pm_list->ps->op,
- e, LCUP_PSEARCH_BY_SCOPEOUT);
+ e, LDAP_PSEARCH_BY_SCOPEOUT);
LDAP_LIST_REMOVE ( pm_list, link );
pm_prev = pm_list;
pm_list = LDAP_LIST_NEXT ( pm_list, link );
free (pm_prev);
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
done:
if( ltid != NULL ) {
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
int noop = 0;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
struct psid_entry* pm_list;
struct psid_entry* pm_prev;
Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
#endif
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
goto return_results;
}
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !op->o_noop ) {
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY );
+ bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
/* modify entry */
rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e,
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( rc == LDAP_SUCCESS && !op->o_noop ) {
/* Loop through in-scope entries for each psearch spec */
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
- bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY );
+ bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
}
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
bdb_psearch(be, conn, op, pm_list->ps->op,
- e, LCUP_PSEARCH_BY_SCOPEOUT);
+ e, LDAP_PSEARCH_BY_SCOPEOUT);
LDAP_LIST_REMOVE ( pm_list, link );
pm_prev = pm_list;
pm_list = LDAP_LIST_NEXT ( pm_list, link );
free (pm_prev);
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
}
if( ltid != NULL ) {
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
);
void bdb_cache_release_all( Cache *cache );
+/*
+ * lcup.c
+ */
+
#ifdef LDAP_CLIENT_UPDATE
int bdb_abandon(
BackendDB *be,
Connection *conn,
ber_int_t id
);
+#endif
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
int bdb_add_psearch_spec(
BackendDB *be,
Connection *conn,
Filter *filter,
struct berval *fstr,
AttributeName *attrs,
- int attrsonly
+ int attrsonly,
+ int protocol
);
int bdb_psearch(
Entry *entry,
int psearch_type
);
+#endif
+
+/*
+ * search.c
+ */
+#ifdef LDAP_CLIENT_UPDATE
+int
+bdb_build_lcup_update_ctrl(
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int entry_count,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv,
+ int isdeleted );
+
+int
+bdb_build_lcup_done_ctrl(
+ Connection *conn,
+ Operation *op,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv );
+#endif
+
+#ifdef LDAP_SYNC
+int
+bdb_build_sync_state_ctrl(
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int entry_sync_state,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ int send_cookie,
+ struct berval *latest_entrycsn_bv );
+
+int
+bdb_build_sync_done_ctrl(
+ Connection *conn,
+ Operation *op,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ int send_cookie,
+ struct berval *latest_entrycsn_bv );
+
+int
+bdb_send_ldap_intermediate(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ const char *matched,
+ const char *text,
+ BerVarray refs,
+ const char *rspoid,
+ int state,
+ struct berval *cookie,
+ LDAPControl **ctrls );
#endif
#ifdef BDB_REUSE_LOCKERS
int tentries = 0;
ID lastid = NOID;
-#ifdef LDAP_CLIENT_UPDATE
- Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+ Filter cookief, csnfnot, csnfeq, csnfand, csnfge;
AttributeAssertion aa_ge, aa_eq;
int entry_count = 0;
- struct berval entrycsn_bv = { 0, NULL };
- struct berval latest_entrycsn_bv = { 0, NULL };
-#endif /* LDAP_CLIENT_UPDATE */
+ struct berval latest_entrycsn_bv = { 0, NULL };
+ LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS];
+ int num_ctrls = 0;
+#endif
+
+#ifdef LDAP_SYNC
+ int rc_sync = 0;
+ int entry_sync_state;
+ AttributeName null_attr;
+#endif
struct slap_limits_set *limit = NULL;
int isroot = 0;
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) {
- bdb_add_psearch_spec( be, conn, op, base, base, scope,
- deref, slimit, tlimit, filter, filterstr, attrs, attrsonly );
+ bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
+ tlimit, filter, filterstr, attrs, attrsonly, LDAP_CLIENT_UPDATE );
return LDAP_SUCCESS;
}
#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ /* psearch needs to be registered before refresh begins */
+ /* psearch and refresh transmission is serialized in send_ldap_ber() */
+ if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
+ bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
+ tlimit, filter, filterstr, attrs, attrsonly, LDAP_SYNC );
+ }
+ null_attr.an_desc = NULL;
+ null_attr.an_oc = NULL;
+ null_attr.an_name.bv_len = 0;
+ null_attr.an_name.bv_val = NULL;
+#endif
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+ for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
+ ctrls[num_ctrls] = NULL;
+ num_ctrls = 0;
+#endif
manageDSAit = get_manageDSAit( op );
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
- lcupf.f_choice = LDAP_FILTER_AND;
- lcupf.f_and = &csnfnot;
- lcupf.f_next = NULL;
+ cookief.f_choice = LDAP_FILTER_AND;
+ cookief.f_and = &csnfnot;
+ cookief.f_next = NULL;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
ber_dupbv( &csnfge.f_av_value, &op->o_clientupdate_state );
csnfge.f_next = filter;
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+ cookief.f_choice = LDAP_FILTER_AND;
+ cookief.f_and = &csnfnot;
+ cookief.f_next = NULL;
+
+ csnfnot.f_choice = LDAP_FILTER_NOT;
+ csnfnot.f_not = &csnfeq;
+ csnfnot.f_next = &csnfand;
+
+ csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+ csnfeq.f_ava = &aa_eq;
+ csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfeq.f_av_value, &op->o_sync_state );
+
+ csnfand.f_choice = LDAP_FILTER_AND;
+ csnfand.f_and = &csnfge;
+ csnfand.f_next = NULL;
+
+ csnfge.f_choice = LDAP_FILTER_GE;
+ csnfge.f_ava = &aa_ge;
+ csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+ ber_dupbv( &csnfge.f_av_value, &op->o_sync_state );
+ csnfge.f_next = filter;
+ }
+#endif
for ( id = bdb_idl_first( candidates, &cursor );
id != NOID;
/* if it matches the filter and scope, send it */
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
- rc = test_filter( be, conn, op, e, &lcupf );
+ rc = test_filter( be, conn, op, e, &cookief );
+ } else
+#endif
+#ifdef LDAP_SYNC
+ if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+ rc_sync = test_filter( be, conn, op, e, &cookief );
+ rc = test_filter( be, conn, op, e, filter );
+ if ( rc == LDAP_COMPARE_TRUE ) {
+ if ( rc_sync == LDAP_COMPARE_TRUE ) {
+ entry_sync_state = LDAP_SYNC_ADD;
+ } else {
+ entry_sync_state = LDAP_SYNC_PRESENT;
+ }
+ }
} else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
{
rc = test_filter( be, conn, op, e, filter );
}
{
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
- Attribute* a;
- int ret;
- int res;
- const char *text = NULL;
- LDAPControl *ctrls[2];
- char berbuf[LBER_ELEMENT_SIZEOF];
- BerElement *ber = (BerElement *)berbuf;
-
- ber_init2( ber, 0, LBER_USE_DER );
-
- entry_count++;
-
- ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
- ctrls[1] = NULL;
-
- if ( entry_count % op->o_clientupdate_interval == 0 ) {
- /* Send cookie */
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- AttributeDescription *desc = a->a_desc;
- if ( desc == slap_schema.si_ad_entryCSN ) {
- ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
- if ( latest_entrycsn_bv.bv_val == NULL ) {
- ber_dupbv( &latest_entrycsn_bv, &entrycsn_bv );
- } else {
- res = value_match( &ret, desc,
- desc->ad_type->sat_ordering,
- SLAP_MR_ASSERTION_SYNTAX_MATCH,
- &entrycsn_bv, &latest_entrycsn_bv, &text );
- if ( res != LDAP_SUCCESS ) {
- ret = 0;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: value_match failed\n",
- 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_search: value_match failed\n",
- 0, 0, 0 );
-#endif
- }
-
- if ( ret > 0 ) {
- ch_free( latest_entrycsn_bv.bv_val );
- latest_entrycsn_bv.bv_val = NULL;
- ber_dupbv( &latest_entrycsn_bv,
- &entrycsn_bv );
- }
- }
- }
- }
-
- ber_printf( ber,
- "{bb{sON}N}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_FALSE,
- LCUP_COOKIE_OID, &entrycsn_bv );
-
- ch_free( entrycsn_bv.bv_val );
- entrycsn_bv.bv_val = NULL;
-
- } else {
- /* Do not send cookie */
- ber_printf( ber,
- "{bbN}",
- SLAP_LCUP_STATE_UPDATE_FALSE,
- SLAP_LCUP_ENTRY_DELETED_FALSE );
- }
+ rc = bdb_build_lcup_update_ctrl( conn, op, e, ++entry_count, ctrls,
+ num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
+ if ( rc != LDAP_SUCCESS )
+ goto done;
+ result = send_search_entry( be, conn, op,
+ e, attrs, attrsonly, ctrls);
- ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
- ctrls[0]->ldctl_iscritical = op->o_clientupdate;
- ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
- if ( ret < 0 ) {
- ber_free_buf( ber );
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: ber_flatten2 failed\n",
- 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_search: ber_flatten2 failed\n",
- 0, 0, 0 );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
+ } else
#endif
- send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
+#ifdef LDAP_SYNC
+ if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+ rc = bdb_build_sync_state_ctrl( conn, op, e, entry_sync_state, ctrls,
+ num_ctrls++, 0, &latest_entrycsn_bv );
+ if ( rc != LDAP_SUCCESS )
goto done;
- }
- result = send_search_entry( be, conn, op,
- e, attrs, attrsonly, ctrls);
+ if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
+ result = send_search_entry( be, conn, op,
+ e, attrs, attrsonly, ctrls);
+ } else { /* PRESENT */
+ result = send_search_entry( be, conn, op,
+ e, &null_attr, attrsonly, ctrls);
+ }
- ber_free_buf( ber );
- ch_free( ctrls[0] );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
} else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+
{
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, NULL);
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
- int ret;
- LDAPControl *ctrls[2];
- char berbuf[LBER_ELEMENT_SIZEOF];
- BerElement *ber = (BerElement *)berbuf;
-
- ber_init2( ber, NULL, LBER_USE_DER );
+ bdb_build_lcup_done_ctrl( conn, op, ctrls, num_ctrls++, &latest_entrycsn_bv );
- ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
- ctrls[1] = NULL;
-
- ber_printf( ber, "{sO", LCUP_COOKIE_OID, &latest_entrycsn_bv );
- ber_printf( ber, "N}" );
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, ctrls, nentries );
- ctrls[0]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
- ctrls[0]->ldctl_iscritical = op->o_clientupdate;
- ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
+ ch_free( latest_entrycsn_bv.bv_val );
+ latest_entrycsn_bv.bv_val = NULL;
- if ( ret < 0 ) {
- ber_free_buf( ber );
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: ber_flatten2 failed\n", 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE, "bdb_search: ber_flatten2 failed\n",
- 0, 0, 0 );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
+ } else
#endif
- send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
- goto done;
+#ifdef LDAP_SYNC
+ if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+ if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
+ /* refreshAndPersist mode */
+ bdb_send_ldap_intermediate( conn, op,
+ LDAP_SUCCESS, NULL, NULL, NULL, LDAP_SYNC_INFO,
+ LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv, NULL );
+ } else {
+ /* refreshOnly mode */
+ bdb_build_sync_done_ctrl( conn, op, ctrls, num_ctrls++, 1, &latest_entrycsn_bv );
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, ctrls, nentries );
+ if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+ ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+ ch_free( ctrls[--num_ctrls] );
+ ctrls[num_ctrls] = NULL;
}
- send_search_result( conn, op,
- v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
- NULL, NULL, v2refs, ctrls, nentries );
-
ch_free( latest_entrycsn_bv.bv_val );
latest_entrycsn_bv.bv_val = NULL;
- ch_free( ctrls[0] );
- ber_free_buf( ber );
} else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
{
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
ch_free( csnfge.f_av_value.bv_val );
}
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+ if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
+ ch_free( csnfeq.f_av_value.bv_val );
+ }
+
+ if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
+ ch_free( csnfge.f_av_value.bv_val );
+ }
+ }
+#endif
LOCK_ID_FREE (bdb->bi_dbenv, locker );
(void) ber_free_buf( ber );
}
+#ifdef LDAP_CLIENT_UPDATE
+int
+bdb_build_lcup_update_ctrl(
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int entry_count,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv,
+ int isdeleted )
+{
+ Attribute* a;
+ int ret;
+ int res;
+ int rc;
+ const char *text = NULL;
+
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+
+ struct berval entrycsn_bv = { 0, NULL };
+
+ ber_init2( ber, 0, LBER_USE_DER );
+
+ ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+ for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+ AttributeDescription *desc = a->a_desc;
+ if ( desc == slap_schema.si_ad_entryCSN ) {
+ ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
+ if ( latest_entrycsn_bv->bv_val == NULL ) {
+ ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+ } else {
+ res = value_match( &ret, desc,
+ desc->ad_type->sat_ordering,
+ SLAP_MR_ASSERTION_SYNTAX_MATCH,
+ &entrycsn_bv, latest_entrycsn_bv, &text );
+ if ( res != LDAP_SUCCESS ) {
+ ret = 0;
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_search: value_match failed\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_search: value_match failed\n",
+ 0, 0, 0 );
+#endif
+ }
+
+ if ( ret > 0 ) {
+ ch_free( latest_entrycsn_bv->bv_val );
+ latest_entrycsn_bv->bv_val = NULL;
+ ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+ }
+ }
+ }
+ }
+
+ if ( entry_count % op->o_clientupdate_interval == 0 )
+ ber_printf( ber,
+ "{bb{sON}N}",
+ SLAP_LCUP_STATE_UPDATE_FALSE,
+ isdeleted,
+ LDAP_LCUP_COOKIE_OID, &entrycsn_bv );
+ else /* Do not send cookie */
+ ber_printf( ber,
+ "{bbN}",
+ SLAP_LCUP_STATE_UPDATE_FALSE,
+ isdeleted );
+
+ ch_free( entrycsn_bv.bv_val );
+ entrycsn_bv.bv_val = NULL;
+
+ ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
+ ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
+ ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+ ber_free_buf( ber );
+
+ if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc=LDAP_OTHER,
+ NULL, "internal error", NULL, NULL );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_build_lcup_done_ctrl(
+ Connection *conn,
+ Operation *op,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv )
+{
+ int ret, rc;
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+ ber_printf( ber, "{sO", LDAP_LCUP_COOKIE_OID, latest_entrycsn_bv );
+ ber_printf( ber, "N}" );
+
+ ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
+ ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
+ ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+ ber_free_buf( ber );
+
+ if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc=LDAP_OTHER,
+ NULL, "internal error", NULL, NULL );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+#ifdef LDAP_SYNC
+int
+bdb_build_sync_state_ctrl(
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int entry_sync_state,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ int send_cookie,
+ struct berval *latest_entrycsn_bv )
+{
+ Attribute* a;
+ int ret;
+ int res;
+ int rc;
+ const char *text = NULL;
+
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+
+ struct berval entryuuid_bv = { 0, NULL };
+ struct berval entrycsn_bv = { 0, NULL };
+
+ ber_init2( ber, 0, LBER_USE_DER );
+
+ ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+ for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+ AttributeDescription *desc = a->a_desc;
+ if ( desc == slap_schema.si_ad_entryCSN ) {
+ ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
+ if ( latest_entrycsn_bv->bv_val == NULL ) {
+ ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+ } else {
+ res = value_match( &ret, desc,
+ desc->ad_type->sat_ordering,
+ SLAP_MR_ASSERTION_SYNTAX_MATCH,
+ &entrycsn_bv, latest_entrycsn_bv, &text );
+ if ( res != LDAP_SUCCESS ) {
+ ret = 0;
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_search: value_match failed\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_search: value_match failed\n",
+ 0, 0, 0 );
+#endif
+ }
+ if ( ret > 0 ) {
+ ch_free( latest_entrycsn_bv->bv_val );
+ latest_entrycsn_bv->bv_val = NULL;
+ ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+ }
+ }
+ } else if ( desc == slap_schema.si_ad_entryUUID ) {
+ ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
+ }
+ }
+
+ if ( send_cookie )
+ ber_printf( ber, "{eOON}", entry_sync_state, &entryuuid_bv, &entrycsn_bv );
+ else
+ ber_printf( ber, "{eON}", entry_sync_state, &entryuuid_bv );
+
+ ch_free( entrycsn_bv.bv_val );
+ entrycsn_bv.bv_val = NULL;
+ ch_free( entryuuid_bv.bv_val );
+ entryuuid_bv.bv_val = NULL;
+
+ ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
+ ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
+ ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+ ber_free_buf( ber );
+
+ if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_build_sync_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_build_sync_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc=LDAP_OTHER,
+ NULL, "internal error", NULL, NULL );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_build_sync_done_ctrl(
+ Connection *conn,
+ Operation *op,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ int send_cookie,
+ struct berval *latest_entrycsn_bv )
+{
+ int ret,rc;
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+ if ( send_cookie ) {
+ ber_printf( ber, "{ON}", latest_entrycsn_bv );
+ } else {
+ ber_printf( ber, "{N}" );
+ }
+
+ ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
+ ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
+ ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+ ber_free_buf( ber );
+
+ if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc=LDAP_OTHER,
+ NULL, "internal error", NULL, NULL );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_send_ldap_intermediate(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ const char *matched,
+ const char *text,
+ BerVarray refs,
+ const char *rspoid,
+ int state,
+ struct berval *cookie,
+ LDAPControl **ctrls )
+{
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+ struct berval rspdata;
+
+ int ret, rc;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ if ( cookie == NULL )
+ ber_printf( ber, "{eN}", state );
+ else
+ ber_printf( ber, "{eON}", state, cookie );
+
+ ret = ber_flatten2( ber, &rspdata, 0 );
+
+ if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc=LDAP_OTHER,
+ NULL, "internal error", NULL, NULL );
+ return ret;
+ }
+
+ send_ldap_intermediate_resp( conn, op, err, matched, text, refs, rspoid, &rspdata, ctrls );
+
+ ber_free_buf( ber );
+
+ return LDAP_SUCCESS;
+}
+#endif
int found = 0;
int opid;
BerElement *ber;
+ int i;
assert( reqoid != NULL );
assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 );
}
if ( !found ) {
+#ifdef LDAP_SYNC
+ for ( i = 0; i < nbackends; i++ ) {
+ if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ if ( bdb_cancel( &backends[i], conn, opid ) == LDAP_SUCCESS ) {
+ return LDAP_SUCCESS;
+ } else {
+ *text = "message ID not found";
+ return LDAP_NO_SUCH_OPERATION;
+ }
+ }
+#else
*text = "message ID not found";
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- return LDAP_NO_SUCH_OPERATION;
+ return LDAP_NO_SUCH_OPERATION;
+#endif
}
if ( op->o_cancel != LDAP_CANCEL_NONE ) {
return rc;
}
+
LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next);
LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL;
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+ if ( arg->co_op->o_cancel == LDAP_CANCEL_ACK )
+ goto co_op_free;
+#endif
#ifdef LDAP_CLIENT_UPDATE
- if ( !( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
-#endif /* LDAP_CLIENT_UPDATE */
- {
- slap_op_free( arg->co_op );
- }
+ if ( ( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
+ goto no_co_op_free;
+#endif
+#ifdef LDAP_SYNC
+ if ( ( arg->co_op->o_sync_mode & SLAP_SYNC_PERSIST ) )
+ goto no_co_op_free;
+#endif
+
+co_op_free:
+
+ slap_op_free( arg->co_op );
+
+no_co_op_free:
+
arg->co_op = NULL;
arg->co_conn = NULL;
free( (char *) arg );
#ifdef LDAP_CLIENT_UPDATE
static SLAP_CTRL_PARSE_FN parseClientUpdate;
#endif
+#ifdef LDAP_SYNC
+static SLAP_CTRL_PARSE_FN parseLdupSync;
+#endif
#undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
{ LDAP_CONTROL_CLIENT_UPDATE,
SLAP_CTRL_SEARCH, NULL,
parseClientUpdate },
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+ { LDAP_CONTROL_SYNC,
+ SLAP_CTRL_SEARCH, NULL,
+ parseLdupSync },
+#endif
{ NULL, 0, NULL, 0 }
};
return LDAP_PROTOCOL_ERROR;
}
+#ifdef LDAP_SYNC
+ if ( op->o_sync != SLAP_NO_CONTROL ) {
+ *text = "LDAP Client Update and Sync controls used together";
+ return LDAP_PROTOCOL_ERROR;
+ }
+#endif
+
if ( ctrl->ldctl_value.bv_len == 0 ) {
*text = "LCUP client update control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
return LDAP_PROTOCOL_ERROR;
}
- if ( tag == LDAP_TAG_COOKIE ) {
+ if ( tag == LDAP_LCUP_TAG_COOKIE ) {
if ( (tag = ber_scanf( ber, /*{*/ "{mm}}",
&scheme, &cookie )) == LBER_ERROR ) {
*text = "LCUP client update control : decoding error";
return LDAP_SUCCESS;
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+
+#ifdef LDAP_SYNC
+static int parseLdupSync (
+ Connection *conn,
+ Operation *op,
+ LDAPControl *ctrl,
+ const char **text )
+{
+ ber_tag_t tag;
+ BerElement *ber;
+ ber_int_t mode;
+ ber_len_t len;
+ struct berval cookie = { 0, NULL };
+
+ if ( op->o_sync != SLAP_NO_CONTROL ) {
+ *text = "LDAP Sync control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+#ifdef LDAP_CLIENT_UPDATE
+ if ( op->o_clientupdate != SLAP_NO_CONTROL ) {
+ *text = "LDAP Sync and LDAP Client Update controls used together";
+ return LDAP_PROTOCOL_ERROR;
+ }
+#endif
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ *text = "LDAP Sync control value is empty (or absent)";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ /* Parse the control value
+ * syncRequestValue ::= SEQUENCE {
+ * mode ENUMERATED {
+ * -- 0 unused
+ * refreshOnly (1),
+ * -- 2 reserved
+ * refreshAndPersist (3)
+ * },
+ * cookie syncCookie OPTIONAL
+ * }
+ */
+
+ ber = ber_init( &ctrl->ldctl_value );
+ if( ber == NULL ) {
+ *text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
+ *text = "LDAP Sync control : mode decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ switch( mode ) {
+ case LDAP_SYNC_REFRESH_ONLY:
+ mode = SLAP_SYNC_REFRESH;
+ break;
+ case LDAP_SYNC_REFRESH_AND_PERSIST:
+ mode = SLAP_SYNC_REFRESH_AND_PERSIST;
+ break;
+ default:
+ *text = "LDAP Sync control : unknown update mode";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+
+ if ( tag == LDAP_SYNC_TAG_COOKIE ) {
+ if (( ber_scanf( ber, /*{*/ "m}",
+ &cookie )) == LBER_ERROR ) {
+ *text = "LDAP Sync control : cookie decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ } else {
+ if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
+ *text = "LDAP Sync control : decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ cookie.bv_len = 0;
+ cookie.bv_val = NULL;
+ }
+
+ /* TODO : Cookie Scheme Validation */
+#if 0
+ if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) {
+ *text = "Unsupported LCUP cookie scheme";
+ return LCUP_UNSUPPORTED_SCHEME;
+ }
+
+ if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) {
+ *text = "Invalid LCUP cookie";
+ return LCUP_INVALID_COOKIE;
+ }
+#endif
+
+ ber_dupbv( &op->o_sync_state, &cookie );
+
+ (void) ber_free( ber, 1 );
+
+ op->o_sync_mode = (char) mode;
+
+ op->o_sync = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ return LDAP_SUCCESS;
+}
+#endif
if ( op->o_clientupdate_state.bv_val != NULL ) {
free( op->o_clientupdate_state.bv_val );
}
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+ if ( op->o_sync_state.bv_val != NULL ) {
+ free( op->o_sync_state.bv_val );
+ }
+#endif
#if defined( LDAP_SLAPI )
if ( op->o_pb != NULL ) {
#endif /* LDAP_SLAPI */
return_results:;
+
#ifdef LDAP_CLIENT_UPDATE
- if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
-#endif /* LDAP_CLIENT_UPDATE */
- {
- if( pbase.bv_val != NULL) free( pbase.bv_val );
- if( nbase.bv_val != NULL) free( nbase.bv_val );
+ if ( ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
+ return rc;
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+ else
+#endif
+#ifdef LDAP_SYNC
+ if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) )
+ return rc;
+#endif
+
+ if( pbase.bv_val != NULL) free( pbase.bv_val );
+ if( nbase.bv_val != NULL) free( nbase.bv_val );
- if( fstr.bv_val != NULL) free( fstr.bv_val );
- if( filter != NULL) filter_free( filter );
- if( an != NULL ) free( an );
+ if( fstr.bv_val != NULL) free( fstr.bv_val );
+ if( filter != NULL) filter_free( filter );
+ if( an != NULL ) free( an );
#ifdef LDAP_SLAPI
- if( attrs != NULL) ch_free( attrs );
+ if( attrs != NULL) ch_free( attrs );
#endif /* LDAP_SLAPI */
- }
return rc;
}
} PagedResultsState;
-#ifdef LDAP_CLIENT_UPDATE
-#define LCUP_PSEARCH_BY_ADD 0x01
-#define LCUP_PSEARCH_BY_DELETE 0x02
-#define LCUP_PSEARCH_BY_PREMODIFY 0x03
-#define LCUP_PSEARCH_BY_MODIFY 0x04
-#define LCUP_PSEARCH_BY_SCOPEOUT 0x05
-
-struct lcup_search_spec {
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+#define LDAP_PSEARCH_BY_ADD 0x01
+#define LDAP_PSEARCH_BY_DELETE 0x02
+#define LDAP_PSEARCH_BY_PREMODIFY 0x03
+#define LDAP_PSEARCH_BY_MODIFY 0x04
+#define LDAP_PSEARCH_BY_SCOPEOUT 0x05
+
+struct ldap_psearch_spec {
struct slap_op *op;
struct berval *base;
struct berval *nbase;
struct berval *filterstr;
AttributeName *attrs;
int attrsonly;
- struct lcup_entry *elist;
- ldap_pvt_thread_mutex_t elist_mutex;
+ int protocol;
int entry_count;
- LDAP_LIST_ENTRY(lcup_search_spec) link;
+ LDAP_LIST_ENTRY(ldap_psearch_spec) link;
};
struct psid_entry {
- struct lcup_search_spec* ps;
+ struct ldap_psearch_spec* ps;
LDAP_LIST_ENTRY(psid_entry) link;
};
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
/*
#define SLAP_LCUP_NONE (0x0)
#define SLAP_LCUP_SYNC (0x1)
#define SLAP_LCUP_PERSIST (0x2)
-#define SLAP_LCUP_SYNC_AND_PERSIST (0x3)
+#define SLAP_LCUP_SYNC_AND_PERSIST (0x3)
ber_int_t o_clientupdate_interval;
struct berval o_clientupdate_state;
- LDAP_LIST_HEAD(lss, lcup_search_spec) psearch_spec;
+#endif
+
+#ifdef LDAP_SYNC
+ char o_sync;
+ char o_sync_mode;
+#define SLAP_SYNC_NONE (0x0)
+#define SLAP_SYNC_REFRESH (0x1)
+#define SLAP_SYNC_PERSIST (0x2)
+#define SLAP_SYNC_REFRESH_AND_PERSIST (0x3)
+ struct berval o_sync_state;
+#endif
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+ LDAP_LIST_HEAD(lss, ldap_psearch_spec) psearch_spec;
LDAP_LIST_HEAD(pe, psid_entry) premodify_list;
LDAP_LIST_ENTRY(slap_op) link;
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
#ifdef LDAP_CONNECTIONLESS
Sockaddr o_peeraddr; /* UDP peer address */
#define SLAP_LCUP_ENTRY_DELETED_FALSE 0
#endif /* LDAP_CLIENT_UPDATE */
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+#define SLAP_SEARCH_MAX_CTRLS 10
+#endif
+
LDAP_END_DECL
#include "proto-slap.h"