+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static void
+send_pagerequest_response(
+ Operation *op,
+ SlapReply *rs,
+ ID lastid,
+ int tentries )
+{
+ LDAPControl ctrl, *ctrls[2];
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+ struct berval cookie = { 0, NULL };
+ PagedResultsCookie respcookie;
+
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ENTRY,
+ "send_pagerequest_response: lastid: (0x%08lx) "
+ "nentries: (0x%081x)\n",
+ lastid, rs->sr_nentries, NULL );
+#else
+ Debug(LDAP_DEBUG_ARGS, "send_pagerequest_response: lastid: (0x%08lx) "
+ "nentries: (0x%081x)\n", lastid, rs->sr_nentries, NULL );
+#endif
+
+ ctrl.ldctl_value.bv_val = NULL;
+ ctrls[0] = &ctrl;
+ ctrls[1] = NULL;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ respcookie = ( PagedResultsCookie )lastid;
+ op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
+ cookie.bv_len = sizeof( respcookie );
+ cookie.bv_val = (char *)&respcookie;
+
+ /*
+ * FIXME: we should consider sending an estimate of the entries
+ * left, after appropriate security check is done
+ */
+ ber_printf( ber, "{iO}", tentries, &cookie );
+
+ if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
+ goto done;
+ }
+
+ ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+ ctrls[0]->ldctl_iscritical = 0;
+
+ rs->sr_ctrls = ctrls;
+ rs->sr_err = LDAP_SUCCESS;
+ send_ldap_result( op, rs );
+
+done:
+ (void) ber_free_buf( ber );
+}
+#endif
+
+#ifdef LDAP_CLIENT_UPDATE
+int
+bdb_build_lcup_update_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ Entry *e,
+ int entry_count,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv,
+ int isdeleted )
+{
+ Attribute* a;
+ int ret;
+ int res;
+ 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, 0,
+ &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_CUP_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_error( op, rs, LDAP_OTHER, "internal error" );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_build_lcup_done_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ struct berval *latest_entrycsn_bv )
+{
+ int ret;
+ 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, "{sON}", LDAP_CUP_COOKIE_OID, latest_entrycsn_bv );
+
+ 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_error( op, rs, LDAP_OTHER, "internal error" );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+#ifdef LDAP_SYNC
+int
+bdb_build_sync_state_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ 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;
+ 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, 0,
+ &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_error( op, rs, LDAP_OTHER, "internal error" );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_build_sync_done_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl **ctrls,
+ int num_ctrls,
+ int send_cookie,
+ struct berval *latest_entrycsn_bv )
+{
+ int ret;
+ 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_error( op, rs, LDAP_OTHER, "internal error" );
+ return ret;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+bdb_send_ldap_intermediate(
+ Operation *op,
+ SlapReply *rs,
+ int state,
+ struct berval *cookie )
+{
+ char berbuf[LBER_ELEMENT_SIZEOF];
+ BerElement *ber = (BerElement *)berbuf;
+ struct berval rspdata;
+
+ int ret;
+
+ 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_error( op, rs, LDAP_OTHER, "internal error" );
+ return ret;
+ }
+
+ rs->sr_rspdata = &rspdata;
+ send_ldap_intermediate_resp( op, rs );
+ rs->sr_rspdata = NULL;
+ ber_free_buf( ber );
+
+ return LDAP_SUCCESS;
+}
+#endif