| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "cb.h"
- /*
- * Build a candidate list for this backentry and scope.
- * Could be a BASE, ONELEVEL, or SUBTREE search.
- *
- * Returns:
- * 0 - success
- * <0 - fail
- *
- */
- int
- chainingdb_build_candidate_list ( Slapi_PBlock *pb )
- {
- Slapi_Backend * be;
- Slapi_Operation * op;
- char *target, *filter;
- int scope,attrsonly,sizelimit,timelimit,rc,searchreferral;
- char **attrs=NULL;
- LDAPControl **controls=NULL;
- LDAPControl **ctrls=NULL;
- LDAP *ld=NULL;
- cb_backend_instance *cb = NULL;
- cb_searchContext *ctx=NULL;
- struct timeval timeout;
- time_t optime;
- int doit,parse_rc;
- LDAPMessage *res=NULL;
- char *matched_msg,*error_msg;
- LDAPControl **serverctrls=NULL;
- char **referrals=NULL;
- char *cnxerrbuf=NULL;
- time_t endbefore=0;
- time_t endtime;
- cb_outgoing_conn *cnx;
- slapi_pblock_get( pb, SLAPI_BACKEND, &be );
- cb = cb_get_instance(be);
- slapi_pblock_get( pb, SLAPI_OPERATION, &op );
- slapi_pblock_get( pb, SLAPI_SEARCH_STRFILTER, &filter );
- slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
- slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &target );
- if ( LDAP_SUCCESS != (parse_rc=cb_forward_operation(pb) )) {
- /* Don't return errors */
- if (cb_debug_on()) {
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "local search: base:<%s> scope:<%s> filter:<%s>\n",target,
- scope==LDAP_SCOPE_SUBTREE?"SUBTREE":scope==LDAP_SCOPE_ONELEVEL ? "ONE-LEVEL" : "BASE" , filter);
- }
- ctx = (cb_searchContext *)slapi_ch_calloc(1,sizeof(cb_searchContext));
- ctx->type = CB_SEARCHCONTEXT_ENTRY;
- ctx->data=NULL;
-
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- return 0;
- }
- cb_update_monitor_info(pb,cb,SLAPI_OPERATION_SEARCH);
- /* Check wether the chaining BE is available or not */
- if ( cb_check_availability( cb, pb ) == FARMSERVER_UNAVAILABLE ){
- return -1;
- }
- if (cb_debug_on()) {
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "chained search: base:<%s> scope:<%s> filter:<%s>\n",target,
- scope==LDAP_SCOPE_SUBTREE?"SUBTREE":scope==LDAP_SCOPE_ONELEVEL ? "ONE-LEVEL" : "BASE" , filter);
- }
- slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs );
- slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
- slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
- slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
- slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- if ((scope != LDAP_SCOPE_BASE) && (scope != LDAP_SCOPE_ONELEVEL) && (scope != LDAP_SCOPE_SUBTREE)) {
- cb_send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "Bad scope", 0, NULL );
- return 1;
- }
- searchreferral=cb->searchreferral;
- if (( scope != LDAP_SCOPE_BASE ) && ( searchreferral )) {
- int i;
- struct berval bv,*bvals[2];
- Slapi_Entry ** aciArray=(Slapi_Entry **) slapi_ch_malloc(2*sizeof(Slapi_Entry *));
- Slapi_Entry *anEntry = slapi_entry_alloc();
- slapi_entry_set_dn(anEntry,slapi_ch_strdup(target));
- bvals[1]=NULL;
- bvals[0]=&bv;
- bv.bv_val="referral";
- bv.bv_len=strlen(bv.bv_val);
- slapi_entry_add_values( anEntry, "objectclass", bvals);
- slapi_rwlock_rdlock(cb->rwl_config_lock);
- for (i=0; cb->url_array && cb->url_array[i]; i++) {
- char * anUrl = slapi_ch_smprintf("%s%s",cb->url_array[i],target);
- bv.bv_val=anUrl;
- bv.bv_len=strlen(bv.bv_val);
- slapi_entry_attr_merge( anEntry, "ref", bvals);
- slapi_ch_free((void **)&anUrl);
- }
- slapi_rwlock_unlock(cb->rwl_config_lock);
-
- aciArray[0]=anEntry;
- aciArray[1]=NULL;
- ctx = (cb_searchContext *)slapi_ch_calloc(1,sizeof(cb_searchContext));
- ctx->type = CB_SEARCHCONTEXT_ENTRY;
- ctx->data=aciArray;
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- return 0;
- }
- /*
- ** Time limit management.
- ** Make sure the operation has not expired
- */
- if ( timelimit == -1 ) {
- timeout.tv_sec = timeout.tv_usec = 0;
- } else {
- time_t now=current_time();
- endbefore=optime + timelimit;
- if (now >= endbefore) {
- cb_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL,NULL, 0, NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- return 1;
- }
- timeout.tv_sec=(time_t)timelimit-(now-optime);
- timeout.tv_usec=0;
- }
- /* Operational attribute support for internal searches: */
- /* The front-end relies on the fact that operational attributes */
- /* are returned along with standard attrs when the attr list is */
- /* NULL. To make it work, we need to explicitly request for all*/
- /* possible operational attrs. Too bad. */
- if ( (attrs == NULL) && operation_is_flag_set(op, OP_FLAG_INTERNAL) ) {
- attrs = cb->every_attribute;
- }
- else
- {
- int i;
- if ( attrs != NULL )
- {
- for ( i = 0; attrs[i] != NULL; i++ ) {
- if ( strcasecmp( "nsrole", attrs[i] ) == 0 )
- {
- attrs = cb->every_attribute;
- break;
- }
- }
- }
- }
- /* Grab a connection handle */
- rc = cb_get_connection(cb->pool, &ld, &cnx, &timeout, &cnxerrbuf);
- if (LDAP_SUCCESS != rc) {
- static int warned_get_conn = 0;
- if (!warned_get_conn) {
- slapi_log_error(SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
- "cb_get_connection failed (%d) %s\n",
- rc, ldap_err2string(rc));
- warned_get_conn = 1;
- }
- if (rc == LDAP_TIMELIMIT_EXCEEDED) {
- cb_send_ldap_result(pb, rc, NULL, cnxerrbuf, 0, NULL);
- } else {
- cb_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
- cnxerrbuf, 0, NULL);
- }
- slapi_ch_free_string(&cnxerrbuf);
- /* ping the farm.
- * If the farm is unreachable, we increment the counter */
- cb_ping_farm(cb, NULL, 0);
- return 1;
- }
- /*
- * Control management
- */
- if ( LDAP_SUCCESS != (rc = cb_update_controls( pb,ld,&ctrls,CB_UPDATE_CONTROLS_ADDAUTH ))) {
- cb_send_ldap_result( pb, rc, NULL,NULL, 0, NULL);
- cb_release_op_connection(cb->pool,ld,0);
- return 1;
- }
- if ( slapi_op_abandoned( pb )) {
- cb_release_op_connection(cb->pool,ld,0);
- if ( NULL != ctrls)
- ldap_controls_free(ctrls);
- return 1;
- }
- ctx = (cb_searchContext *) slapi_ch_calloc(1,sizeof(cb_searchContext));
- /*
- ** We need to store the connection handle in the search context
- ** to make sure we reuse it in the next_entry iteration
- ** Indeed, if another thread on this connection detects a problem
- ** on this connection, it may reallocate a new connection and
- ** a call to get_connection may return a new cnx. Too bad.
- */
- ctx->ld=ld;
- ctx->cnx=cnx;
- /* for some reasons, it is an error to pass in a zero'd timeval */
- /* to ldap_search_ext() */
- if ((timeout.tv_sec==0) && (timeout.tv_usec==0))
- timeout.tv_sec=timeout.tv_usec=-1;
- /* heart-beat management */
- if (cb->max_idle_time>0)
- endtime=current_time() + cb->max_idle_time;
- rc=ldap_search_ext(ld ,target,scope,filter,attrs,attrsonly,
- ctrls, NULL, &timeout,sizelimit, &(ctx->msgid) );
- if ( NULL != ctrls)
- ldap_controls_free(ctrls);
- if ( LDAP_SUCCESS != rc ) {
- cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string(rc), 0, NULL);
- cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
- slapi_ch_free((void **) &ctx);
- return 1;
- }
- /*
- ** Need to get the very first result to handle
- ** errors properly, especially no search base.
- */
- doit=1;
- while (doit) {
- if (cb_check_forward_abandon(cb,pb,ctx->ld,ctx->msgid)) {
- slapi_ch_free((void **) &ctx);
- return 1;
- }
- rc=ldap_result(ld,ctx->msgid,LDAP_MSG_ONE,&cb->abandon_timeout,&res);
- switch ( rc ) {
- case -1:
- /* An error occurred. return now */
- rc = slapi_ldap_get_lderrno(ld,NULL,NULL);
- /* tuck away some errors in a OPERATION_ERROR */
- if (CB_LDAP_CONN_ERROR(rc)) {
- cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
- ldap_err2string( rc ), 0, NULL);
- } else {
- cb_send_ldap_result(pb,rc, NULL, NULL,0,NULL);
- }
- cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
- if (res)
- ldap_msgfree(res);
- slapi_ch_free((void **)&ctx);
- return 1;
- case 0:
-
- /* Local timeout management */
- if (timelimit != -1) {
- if (current_time() > endbefore) {
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "Local timeout expiration\n");
- cb_send_ldap_result(pb,LDAP_TIMELIMIT_EXCEEDED,
- NULL,NULL, 0, NULL);
- /* Force connection close */
- cb_release_op_connection(cb->pool,ld,1);
- if (res)
- ldap_msgfree(res);
- slapi_ch_free((void **)&ctx);
- return 1;
- }
- }
- /* heart-beat management */
- if ((rc=cb_ping_farm(cb,cnx,endtime)) != LDAP_SUCCESS) {
- cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
- ldap_err2string(rc), 0, NULL);
- cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
- if (res)
- ldap_msgfree(res);
- slapi_ch_free((void **)&ctx);
- return 1;
- }
- #ifdef CB_YIELD
- DS_Sleep(PR_INTERVAL_NO_WAIT);
- #endif
- break;
- case LDAP_RES_SEARCH_ENTRY:
- case LDAP_RES_SEARCH_REFERENCE:
- /* Some results received */
- /* don't parse result here */
- ctx->pending_result=res;
- ctx->pending_result_type=rc;
- doit=0;
- break;
- case LDAP_RES_SEARCH_RESULT:
- matched_msg=NULL;
- error_msg=NULL;
- referrals=NULL;
- serverctrls=NULL;
- parse_rc=ldap_parse_result(ld,res,&rc,&matched_msg,
- &error_msg,&referrals, &serverctrls, 0 );
- if ( parse_rc != LDAP_SUCCESS ) {
- static int warned_parse_rc = 0;
- if (!warned_parse_rc && error_msg) {
- slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
- "%s%s%s\n",
- matched_msg?matched_msg:"",
- (matched_msg&&(*matched_msg!='\0'))?": ":"",
- error_msg );
- warned_parse_rc = 1;
- }
- cb_send_ldap_result( pb, parse_rc, NULL,
- ENDUSERMSG, 0, NULL );
- rc=-1;
- } else if ( rc != LDAP_SUCCESS ) {
- static int warned_rc = 0;
- if (!warned_rc) {
- slapi_ldap_get_lderrno( ctx->ld,
- &matched_msg, &error_msg );
- slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
- "%s%s%s\n",
- matched_msg?matched_msg:"",
- (matched_msg&&(*matched_msg!='\0'))?": ":"",
- error_msg );
- warned_rc = 1;
- }
- cb_send_ldap_result( pb, rc, NULL, ENDUSERMSG, 0, NULL);
- /* BEWARE: matched_msg and error_msg points */
- /* to ld fields. */
- matched_msg=NULL;
- error_msg=NULL;
- rc=-1;
- }
- slapi_ch_free((void **)&matched_msg);
- slapi_ch_free((void **)&error_msg);
- if (serverctrls)
- ldap_controls_free(serverctrls);
- if (referrals)
- charray_free(referrals);
- if (rc!=LDAP_SUCCESS) {
- cb_release_op_connection(cb->pool,ld,
- CB_LDAP_CONN_ERROR(rc));
- ldap_msgfree(res);
- slapi_ch_free((void **)&ctx);
- return -1;
- }
- /* Store the msg in the ctx */
- /* Parsed in iterate. */
- ctx->pending_result=res;
- ctx->pending_result_type=LDAP_RES_SEARCH_RESULT;
- doit=0;
- }
- }
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- return 0;
- }
- /*
- * Return the next entry in the result set. The entry is returned
- * in the pblock.
- * Returns 0 normally. If -1 is returned, it means that some
- * exceptional condition, e.g. timelimit exceeded has occurred,
- * and this routine has sent a result to the client. If zero
- * is returned and no entry is available in the PBlock, then
- * we've iterated through all the entries.
- */
- int
- chainingdb_next_search_entry ( Slapi_PBlock *pb )
- {
- char *target;
- int sizelimit, timelimit;
- int rc, parse_rc, retcode;
- int i, attrsonly;
- time_t optime;
- LDAPMessage *res=NULL;
- char *matched_msg,*error_msg;
- cb_searchContext *ctx=NULL;
- Slapi_Entry *entry;
- LDAPControl **serverctrls=NULL;
- char **referrals=NULL;
- cb_backend_instance * cb=NULL;
- Slapi_Backend * be;
- time_t endtime;
- matched_msg=error_msg=NULL;
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &ctx );
- slapi_pblock_get( pb, SLAPI_BACKEND, &be );
- slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
- slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &target );
- slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
- slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
- cb = cb_get_instance(be);
- if ( NULL == ctx ) {
- /* End of local search */
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "Unexpected NULL ctx in chainingdb_next_search_entry\n");
- return 0;
- }
- if ( NULL != ctx->readahead) {
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, ctx->readahead);
- if (ctx->tobefreed != ctx->readahead) {
- slapi_entry_free(ctx->tobefreed);
- }
- ctx->tobefreed = ctx->readahead;
- ctx->readahead = NULL;
- cb_set_acl_policy(pb);
- return 0;
- }
- if ( NULL != ctx->tobefreed ) {
- slapi_entry_free(ctx->tobefreed);
- ctx->tobefreed=NULL;
- }
- if ( ctx->type == CB_SEARCHCONTEXT_ENTRY ) {
- int n;
- Slapi_Entry ** ptr;
- if ( (timelimit != -1) && (timelimit != 0)) {
- time_t now=current_time();
- if (now > (optime + timelimit)) {
- cb_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL,NULL, 0, NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- for ( n = 0, ptr=(Slapi_Entry **)ctx->data; ptr != NULL && ptr[n] != NULL; n++ ) {
- slapi_entry_free(ptr[n]);
- }
- if (ctx->data)
- slapi_ch_free((void **)&ctx->data);
- slapi_ch_free((void **)&ctx);
- return -1;
- }
- }
- /*
- ** Return the Slapi_Entry of the result set one
- ** by one
- */
- for ( n = 0, ptr=(Slapi_Entry **)ctx->data; ptr != NULL && ptr[n] != NULL; n++ );
- if ( n != 0) {
- Slapi_Entry * anEntry=ptr[n-1];
- ptr[n-1]=NULL;
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,anEntry);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- cb_set_acl_policy(pb);
- ctx->tobefreed=anEntry;
- } else {
- slapi_ch_free((void **) &ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- }
- return 0;
- }
- /*
- * Grab a connection handle. Should be the same as the one
- * used in the build_candidate list. To be certain of that, grab it from
- * the context.
- */
- /* Poll the server for the results of the search operation.
- * Passing LDAP_MSG_ONE indicates that you want to receive
- * the entries one at a time, as they come in. If the next
- * entry that you retrieve is NULL, there are no more entries.
- */
-
- /* heart-beat management */
- if (cb->max_idle_time>0)
- endtime=current_time() + cb->max_idle_time;
- while (1) {
- if (cb_check_forward_abandon(cb,pb,ctx->ld,ctx->msgid)) {
- /* cnx handle released */
- if (ctx->pending_result)
- ldap_msgfree(ctx->pending_result);
- slapi_ch_free((void **) &ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- return -1;
- }
- /* Check for time limit done by the remote farm server */
- /* Check for size limit done by the remote farm server */
- /* Use pending msg if one is available */
- if (ctx->pending_result) {
- res=ctx->pending_result;
- rc=ctx->pending_result_type;
- ctx->pending_result=NULL;
- } else {
- rc=ldap_result(ctx->ld,ctx->msgid,
- LDAP_MSG_ONE, &cb->abandon_timeout, &res );
- }
- /* The server can return three types of results back to the client,
- * and the return value of ldap_result() indicates the result type:
- * LDAP_RES_SEARCH_ENTRY identifies an entry found by the search,
- * LDAP_RES_SEARCH_REFERENCE identifies a search reference returned
- * by the server, and LDAP_RES_SEARCH_RESULT is the last result
- * sent from the server to the client after the operation completes.
- * We need to check for each of these types of results.
- */
- switch ( rc ) {
- case -1:
- /* An error occurred. */
- rc = slapi_ldap_get_lderrno( ctx->ld, NULL, NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string( rc ), 0, NULL);
-
- if (res)
- ldap_msgfree(res);
- cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(rc));
- slapi_ch_free((void **)&ctx);
- return -1;
- case 0:
- /* heart-beat management */
- if ((rc=cb_ping_farm(cb,ctx->cnx,endtime)) != LDAP_SUCCESS) {
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
- ldap_err2string(rc), 0, NULL);
- if (res)
- ldap_msgfree(res);
- cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(rc));
- slapi_ch_free((void **)&ctx);
- return -1;
- }
- #ifdef CB_YIELD
- DS_Sleep(PR_INTERVAL_NO_WAIT);
- #endif
- break;
- case LDAP_RES_SEARCH_ENTRY:
- /* heart-beat management */
- if (cb->max_idle_time>0)
- endtime=current_time() + cb->max_idle_time;
- /* The server sent one of the entries found by the search */
- if ((entry = cb_LDAPMessage2Entry(ctx->ld,res,attrsonly)) == NULL) {
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,"Invalid entry received.\n");
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL , 0, NULL);
- ldap_msgfree(res);
- cb_release_op_connection(cb->pool,ctx->ld,0);
- slapi_ch_free((void **)&ctx);
- return -1;
- }
- ctx->tobefreed=entry;
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,entry);
- cb_set_acl_policy(pb);
- ldap_msgfree(res);
- return 0;
- case LDAP_RES_SEARCH_REFERENCE:
- /* The server sent a search reference encountered during the
- * search operation.
- */
-
- /* heart-beat management */
- if (cb->max_idle_time>0)
- endtime=current_time() + cb->max_idle_time;
- parse_rc = ldap_parse_reference( ctx->ld, res, &referrals, NULL, 1 );
- if ( parse_rc != LDAP_SUCCESS ) {
- cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
- ldap_err2string( parse_rc ), 0, NULL);
- cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(parse_rc));
- slapi_ch_free((void **)&ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- return -1;
- }
- /*
- ** build a dummy entry on the fly with a ref attribute
- */
- {
- struct berval bv;
- int i;
- struct berval *bvals[2];
- Slapi_Entry *anEntry = slapi_entry_alloc();
- slapi_entry_set_dn(anEntry,slapi_ch_strdup(target));
- bvals[1]=NULL;
- bvals[0]=&bv;
- bv.bv_val="referral";
- bv.bv_len=strlen(bv.bv_val);
- slapi_entry_add_values( anEntry, "objectclass", bvals);
- for (i=0;referrals[i] != NULL; i++) {
- bv.bv_val=referrals[i];
- bv.bv_len=strlen(bv.bv_val);
- slapi_entry_add_values( anEntry, "ref", bvals);
- }
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,anEntry);
- cb_set_acl_policy(pb);
- }
- if (referrals != NULL) {
- slapi_ldap_value_free( referrals );
- }
-
- return 0;
- case LDAP_RES_SEARCH_RESULT:
- /* Parse the final result received from the server. Note the last
- * argument is a non-zero value, which indicates that the
- * LDAPMessage structure will be freed when done.
- */
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
- parse_rc = ldap_parse_result( ctx->ld, res,
- &rc,&matched_msg,&error_msg, &referrals, &serverctrls, 1 );
- if ( parse_rc != LDAP_SUCCESS ) {
- static int warned_parse_rc = 0;
- if (!warned_parse_rc) {
- slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
- "%s%s%s\n",
- matched_msg?matched_msg:"",
- (matched_msg&&(*matched_msg!='\0'))?": ":"",
- ldap_err2string( parse_rc ));
- warned_parse_rc = 1;
- }
- cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
- ENDUSERMSG, 0, NULL );
- retcode=-1;
- } else
- if ( rc != LDAP_SUCCESS ) {
- static int warned_rc = 0;
- slapi_ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg );
- if (!warned_rc) {
- slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
- "%s%s%s\n",
- matched_msg?matched_msg:"",
- (matched_msg&&(*matched_msg!='\0'))?": ":"",
- error_msg );
- warned_rc = 1;
- }
- cb_send_ldap_result( pb, rc, matched_msg, ENDUSERMSG, 0, NULL );
- /* BEWARE: Don't free matched_msg && error_msg */
- /* Points to the ld fields */
- matched_msg=NULL;
- error_msg=NULL;
- retcode=-1;
- } else {
- /* Add control response sent by the farm server */
- for (i=0; serverctrls && serverctrls[i];i++)
- slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, serverctrls[i]);
- retcode=0;
- }
- if (serverctrls)
- ldap_controls_free(serverctrls);
- slapi_ch_free((void **)&matched_msg);
- slapi_ch_free((void **)&error_msg);
- if (referrals)
- charray_free(referrals);
- cb_release_op_connection(cb->pool,ctx->ld,0);
- slapi_ch_free((void **)&ctx);
- return retcode;
- default:
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "chainingdb_next_search_entry:default case.\n");
-
- }
- }
- /* Not reached */
- /* return 0; */
- }
- int
- chaining_back_entry_release ( Slapi_PBlock *pb ) {
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "chaining_back_entry_release\n");
- return 0;
- }
- void
- chaining_back_search_results_release ( void **sr )
- {
- cb_searchContext *ctx = (cb_searchContext *)(*sr);
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "chaining_back_search_results_release\n");
- if (ctx->readahead != ctx->tobefreed) {
- slapi_entry_free(ctx->readahead);
- }
- slapi_entry_free(ctx->tobefreed);
- ctx->tobefreed = NULL;
- slapi_ch_free((void **)&ctx->data);
- slapi_ch_free((void **)&ctx);
- return;
- }
- void
- chainingdb_prev_search_results ( Slapi_PBlock *pb )
- {
- cb_searchContext *ctx = NULL;
- Slapi_Entry *entry = NULL;
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &ctx );
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_ENTRY, &entry );
- ctx->readahead = entry;
- return;
- }
|