summaryrefslogtreecommitdiffstats
path: root/ldap/c-sdk/libraries/libldap/result.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/c-sdk/libraries/libldap/result.c')
-rw-r--r--ldap/c-sdk/libraries/libldap/result.c1473
1 files changed, 0 insertions, 1473 deletions
diff --git a/ldap/c-sdk/libraries/libldap/result.c b/ldap/c-sdk/libraries/libldap/result.c
deleted file mode 100644
index 59c15f811..000000000
--- a/ldap/c-sdk/libraries/libldap/result.c
+++ /dev/null
@@ -1,1473 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/*
- * Copyright (c) 1990 Regents of the University of Michigan.
- * All rights reserved.
- */
-/*
- * result.c - wait for an ldap result
- */
-
-#if 0
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
-#endif
-
-#include "ldap-int.h"
-
-/*
- * Special return values used by some functions (wait4msg() and read1msg()).
- */
-#define NSLDAPI_RESULT_TIMEOUT 0
-#define NSLDAPI_RESULT_ERROR (-1)
-#define NSLDAPI_RESULT_NOT_FOUND (-2)
-
-static int check_response_queue( LDAP *ld, int msgid, int all,
- int do_abandon_check, LDAPMessage **result );
-static int ldap_abandoned( LDAP *ld, int msgid );
-static int ldap_mark_abandoned( LDAP *ld, int msgid );
-static int wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted,
- struct timeval *timeout, LDAPMessage **result );
-static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp,
- LDAPMessage **result );
-static void check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber,
- int ldapversion, int *totalcountp, int *chasingcountp );
-static int build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr );
-static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr );
-#if defined( CLDAP )
-static int cldap_select1( LDAP *ld, struct timeval *timeout );
-#endif
-static void link_pend( LDAP *ld, LDAPPend *lp );
-
-/*
- * ldap_result - wait for an ldap result response to a message from the
- * ldap server. If msgid is -1, any message will be accepted, otherwise
- * ldap_result will wait for a response with msgid. If all is 0 the
- * first message with id msgid will be accepted, otherwise, ldap_result
- * will wait for all responses with id msgid and then return a pointer to
- * the entire list of messages. This is only useful for search responses,
- * which can be of two message types (zero or more entries, followed by an
- * ldap result). The type of the first message received is returned.
- * When waiting, any messages that have been abandoned are discarded.
- *
- * Example:
- * ldap_result( s, msgid, all, timeout, result )
- */
-int
-LDAP_CALL
-ldap_result(
- LDAP *ld,
- int msgid,
- int all,
- struct timeval *timeout,
- LDAPMessage **result
-)
-{
- int rc;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 );
-
- if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
- return( -1 ); /* punt */
- }
-
- LDAP_MUTEX_LOCK( ld, LDAP_RESULT_LOCK );
-
- rc = nsldapi_result_nolock(ld, msgid, all, 1, timeout, result);
-
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESULT_LOCK );
-
- return( rc );
-}
-
-
-int
-nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted,
- struct timeval *timeout, LDAPMessage **result )
-{
- int rc;
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "nsldapi_result_nolock (msgid=%d, all=%d)\n", msgid, all, 0 );
-
- /*
- * First, look through the list of responses we have received on
- * this association and see if the response we're interested in
- * is there. If it is, return it. If not, call wait4msg() to
- * wait until it arrives or timeout occurs.
- */
-
- if ( result == NULL ) {
- LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
- return( -1 );
- }
-
- if ( check_response_queue( ld, msgid, all, 1, result ) != 0 ) {
- LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL );
- rc = (*result)->lm_msgtype;
- } else {
- rc = wait4msg( ld, msgid, all, unlock_permitted, timeout,
- result );
- }
-
- /*
- * XXXmcs should use cache function pointers to hook in memcache
- */
- if ( ld->ld_memcache != NULL && NSLDAPI_SEARCH_RELATED_RESULT( rc ) &&
- !((*result)->lm_fromcache )) {
- ldap_memcache_append( ld, (*result)->lm_msgid,
- (all || NSLDAPI_IS_SEARCH_RESULT( rc )), *result );
- }
-
- return( rc );
-}
-
-
-/*
- * Look through the list of queued responses for a message that matches the
- * criteria in the msgid and all parameters. msgid == LDAP_RES_ANY matches
- * all ids.
- *
- * If an appropriate message is found, a non-zero value is returned and the
- * message is dequeued and assigned to *result.
- *
- * If not, *result is set to NULL and this function returns 0.
- */
-static int
-check_response_queue( LDAP *ld, int msgid, int all, int do_abandon_check,
- LDAPMessage **result )
-{
- LDAPMessage *lm, *lastlm, *nextlm;
- LDAPRequest *lr;
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "=> check_response_queue (msgid=%d, all=%d)\n", msgid, all, 0 );
-
- *result = NULL;
- lastlm = NULL;
- LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK );
- for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
- nextlm = lm->lm_next;
-
- if ( do_abandon_check && ldap_abandoned( ld, lm->lm_msgid ) ) {
- ldap_mark_abandoned( ld, lm->lm_msgid );
-
- if ( lastlm == NULL ) {
- ld->ld_responses = lm->lm_next;
- } else {
- lastlm->lm_next = nextlm;
- }
-
- ldap_msgfree( lm );
-
- continue;
- }
-
- if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) {
- LDAPMessage *tmp;
-
- if ( all == 0
- || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT
- && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE
- && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) )
- break;
-
- for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) {
- if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT )
- break;
- }
-
- if ( tmp == NULL ) {
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- LDAPDebug( LDAP_DEBUG_TRACE,
- "<= check_response_queue NOT FOUND\n",
- 0, 0, 0 );
- return( 0 ); /* no message to return */
- }
-
- break;
- }
- lastlm = lm;
- }
-
- /*
- * if we did not find a message OR if the one we found is a result for
- * a request that is still pending, return failure.
- */
- if ( lm == NULL
- || (( lr = nsldapi_find_request_by_msgid( ld, lm->lm_msgid ))
- != NULL && lr->lr_outrefcnt > 0 )) {
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- LDAPDebug( LDAP_DEBUG_TRACE,
- "<= check_response_queue NOT FOUND\n",
- 0, 0, 0 );
- return( 0 ); /* no message to return */
- }
-
- if ( all == 0 ) {
- if ( lm->lm_chain == NULL ) {
- if ( lastlm == NULL ) {
- ld->ld_responses = lm->lm_next;
- } else {
- lastlm->lm_next = lm->lm_next;
- }
- } else {
- if ( lastlm == NULL ) {
- ld->ld_responses = lm->lm_chain;
- ld->ld_responses->lm_next = lm->lm_next;
- } else {
- lastlm->lm_next = lm->lm_chain;
- lastlm->lm_next->lm_next = lm->lm_next;
- }
- }
- } else {
- if ( lastlm == NULL ) {
- ld->ld_responses = lm->lm_next;
- } else {
- lastlm->lm_next = lm->lm_next;
- }
- }
-
- if ( all == 0 ) {
- lm->lm_chain = NULL;
- }
- lm->lm_next = NULL;
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
-
- *result = lm;
- LDAPDebug( LDAP_DEBUG_TRACE,
- "<= check_response_queue returning msgid %d type %d\n",
- lm->lm_msgid, lm->lm_msgtype, 0 );
- return( 1 ); /* a message was found and returned in *result */
-}
-
-
-/*
- * wait4msg(): Poll for incoming LDAP messages, respecting the timeout.
- *
- * Return values:
- * > 0: message received; value is the tag of the message.
- * NSLDAPI_RESULT_TIMEOUT timeout exceeded.
- * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed.
- */
-static int
-wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted,
- struct timeval *timeout, LDAPMessage **result )
-{
- int err, rc = NSLDAPI_RESULT_NOT_FOUND, msgfound;
- struct timeval tv, *tvp;
- long start_time = 0, tmp_time;
- LDAPConn *lc, *nextlc;
- /* lr points to the specific request we are waiting for, if any */
- LDAPRequest *lr = NULL;
-
-#ifdef LDAP_DEBUG
- if ( timeout == NULL ) {
- LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n",
- 0, 0, 0 );
- } else {
- LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n",
- timeout->tv_sec, (long) timeout->tv_usec, 0 );
- }
-#endif /* LDAP_DEBUG */
-
- /* check the cache */
- if ( ld->ld_cache_on && ld->ld_cache_result != NULL ) {
- /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */
- LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
- rc = (ld->ld_cache_result)( ld, msgid, all, timeout, result );
- LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
- /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */
- if ( rc != NSLDAPI_RESULT_TIMEOUT ) {
- return( rc );
- }
- if ( ld->ld_cache_strategy == LDAP_CACHE_LOCALDB ) {
- LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL );
- return( NSLDAPI_RESULT_TIMEOUT );
- }
- }
-
- /*
- * if we are looking for a specific msgid, check to see if it is
- * associated with a dead connection and return an error if so.
- */
- if ( msgid != LDAP_RES_ANY && msgid != LDAP_RES_UNSOLICITED ) {
- LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );
- if (( lr = nsldapi_find_request_by_msgid( ld, msgid ))
- == NULL ) {
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL,
- nsldapi_strdup( "unknown message id" ));
- return( NSLDAPI_RESULT_ERROR ); /* could not find request for msgid */
- }
- if ( lr->lr_conn != NULL &&
- lr->lr_conn->lconn_status == LDAP_CONNST_DEAD ) {
- nsldapi_free_request( ld, lr, 1 );
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL );
- return( NSLDAPI_RESULT_ERROR ); /* connection dead */
- }
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- }
-
- if ( timeout == NULL ) {
- tvp = NULL;
- } else {
- tv = *timeout;
- tvp = &tv;
- start_time = (long)time( NULL );
- }
-
- rc = NSLDAPI_RESULT_NOT_FOUND;
- while ( rc == NSLDAPI_RESULT_NOT_FOUND ) {
- msgfound = 0;
-#ifdef LDAP_DEBUG
- if ( ldap_debug & LDAP_DEBUG_TRACE ) {
- nsldapi_dump_connection( ld, ld->ld_conns, 1 );
- nsldapi_dump_requests_and_responses( ld );
- }
-#endif /* LDAP_DEBUG */
-
- /*
- * Check if we have some data in a connection's BER buffer.
- * If so, use it.
- */
- LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK );
- LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );
- for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
- if ( lc->lconn_sb->sb_ber.ber_ptr <
- lc->lconn_sb->sb_ber.ber_end ) {
- /* read1msg() might free the connection. */
- rc = read1msg( ld, msgid, all, lc->lconn_sb,
- &lc, result );
- /* Indicate to next segment that we've processed a message
- (or several, via chased refs) this time around. */
- msgfound = 1;
- break;
- }
- }
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK );
-
- if ( !msgfound ) {
- /*
- * There was no buffered data. Poll to check connection
- * status (read/write readiness).
- */
- err = nsldapi_iostatus_poll( ld, tvp );
-
-#if defined( LDAP_DEBUG ) && !defined( macintosh ) && !defined( DOS )
- if ( err == -1 ) {
- LDAPDebug( LDAP_DEBUG_TRACE,
- "nsldapi_iostatus_poll returned -1: errno %d\n",
- LDAP_GET_ERRNO( ld ), 0, 0 );
- }
-#endif
-
-#if !defined( macintosh ) && !defined( DOS )
- /*
- * If the restart option is enabled and the error
- * was EINTR, try again.
- */
- if ( err == -1
- && 0 != ( ld->ld_options & LDAP_BITOPT_RESTART )
- && LDAP_GET_ERRNO( ld ) == EINTR ) {
- continue;
- }
-#endif
-
- /*
- * Handle timeouts (no activity) and fatal errors.
- */
- if ( err == -1 || err == 0 ) {
- LDAP_SET_LDERRNO( ld, (err == -1 ?
- LDAP_SERVER_DOWN : LDAP_TIMEOUT), NULL,
- NULL );
- if ( err == -1 ) {
- LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );
- nsldapi_connection_lost_nolock( ld,
- NULL );
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- rc = NSLDAPI_RESULT_ERROR;
- } else {
- rc = NSLDAPI_RESULT_TIMEOUT;
- }
- return( rc );
- }
-
- /*
- * Check each connection for interesting activity.
- */
- LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK );
- LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );
- for ( lc = ld->ld_conns;
- rc == NSLDAPI_RESULT_NOT_FOUND && lc != NULL;
- lc = nextlc ) {
- nextlc = lc->lconn_next;
-
- /*
- * For connections that are in the CONNECTING
- * state, check for write ready (which
- * indicates that the connection completed) and
- * transition to the CONNECTED state.
- */
- if ( lc->lconn_status == LDAP_CONNST_CONNECTING
- && nsldapi_iostatus_is_write_ready( ld,
- lc->lconn_sb ) ) {
- lc->lconn_status = LDAP_CONNST_CONNECTED;
- LDAPDebug( LDAP_DEBUG_TRACE,
- "wait4msg: connection 0x%p -"
- " LDAP_CONNST_CONNECTING ->"
- " LDAP_CONNST_CONNECTED\n",
- lc, 0, 0 );
- }
-
- if ( lc->lconn_status
- != LDAP_CONNST_CONNECTED ) {
- continue;
- }
-
- /*
- * For connections that are CONNECTED, check
- * for read ready (which indicates that data
- * from server is available), and, for
- * connections with associated requests that
- * have not yet been sent, write ready (okay
- * to send some data to the server).
- */
- if ( nsldapi_iostatus_is_read_ready( ld,
- lc->lconn_sb )) {
- /* read1msg() might free the connection. */
- rc = read1msg( ld, msgid, all,
- lc->lconn_sb, &lc, result );
- }
-
- /*
- * Send pending requests if possible. If there is no lc then
- * it was a child connection closed by read1msg().
- */
- if ( lc && lc->lconn_pending_requests > 0
- && nsldapi_iostatus_is_write_ready( ld,
- lc->lconn_sb )) {
- err = nsldapi_send_pending_requests_nolock(
- ld, lc );
- if ( err == -1 &&
- rc == NSLDAPI_RESULT_NOT_FOUND ) {
- rc = NSLDAPI_RESULT_ERROR;
- }
- }
-
- }
-
- LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
- LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK );
- }
-
- /*
- * It is possible that recursion occurred while chasing
- * referrals and as a result the message we are looking
- * for may have been placed on the response queue. Look
- * for it there before continuing so we don't end up
- * waiting on the network for a message that we already
- * received!
- */
- if ( rc == NSLDAPI_RESULT_NOT_FOUND &&
- check_response_queue( ld, msgid, all, 0, result ) != 0 ) {
- LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL );
- rc = (*result)->lm_msgtype;
- }
-
- /*
- * honor the timeout if specified
- */
- if ( rc == NSLDAPI_RESULT_NOT_FOUND && tvp != NULL ) {
- tmp_time = (long)time( NULL );
- if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) {
- rc = NSLDAPI_RESULT_TIMEOUT;
- LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL,
- NULL );
- break;
- }
-
- LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg: %ld secs to go\n",
- tv.tv_sec, 0, 0 );
- start_time = tmp_time;
- }
- }
-
- return( rc );
-}
-
-
-#define NSLDAPI_REQUEST_COMPLETE( lr ) \
- ( (lr)->lr_outrefcnt <= 0 && \
- (lr)->lr_res_msgtype != LDAP_RES_SEARCH_ENTRY && \
- (lr)->lr_res_msgtype != LDAP_RES_SEARCH_REFERENCE )
-
-/*
- * read1msg() should be called with LDAP_CONN_LOCK and LDAP_REQ_LOCK locked.
- *
- * Return values:
- * > 0: message received; value is the tag of the message.
- * NSLDAPI_RESULT_TIMEOUT timeout exceeded.
- * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed.
- * NSLDAPI_RESULT_NOT_FOUND message not yet complete; keep waiting.
- *
- * The LDAPConn passed in my be freed by read1msg() if the reference count
- * shows that it's no longer needed.
- */
-static int
-read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp,
- LDAPMessage **result )
-{
- BerElement *ber;
- LDAPMessage *new, *l, *prev, *chainprev, *tmp;
- ber_int_t id;
- ber_tag_t tag;
- ber_len_t len;
- int terrno, lderr, foundit = 0;
- LDAPRequest *lr;
- int rc, has_parent, message_can_be_returned;
- int manufactured_result = 0;
- LDAPConn *lc = *lcp;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 );
-
- message_can_be_returned = 1; /* the usual case... */
-
- /*
- * if we are not already in the midst of reading a message, allocate
- * a ber that is associated with this connection
- */
- if ( lc->lconn_ber == NULLBER && nsldapi_alloc_ber_with_options( ld,
- &lc->lconn_ber ) != LDAP_SUCCESS ) {
- return( NSLDAPI_RESULT_ERROR );
- }
-
- /*
- * ber_get_next() doesn't set errno on EOF, so we pre-set it to
- * zero to avoid getting tricked by leftover "EAGAIN" errors
- */
- LDAP_SET_ERRNO( ld, 0 );
-
- /* get the next message */
- if ( (tag = ber_get_next( sb, &len, lc->lconn_ber ))
- != LDAP_TAG_MESSAGE ) {
- terrno = LDAP_GET_ERRNO( ld );
- if ( terrno == EWOULDBLOCK || terrno == EAGAIN ) {
- return( NSLDAPI_RESULT_NOT_FOUND ); /* try again */
- }
- LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
- LDAP_LOCAL_ERROR), NULL, NULL );
- if ( tag == LBER_DEFAULT ) {
- nsldapi_connection_lost_nolock( ld, sb );
- }
- return( NSLDAPI_RESULT_ERROR );
- }
-
- /*
- * Since we have received a complete message now, we pull this ber
- * out of the connection structure and never read into it again.
- */
- ber = lc->lconn_ber;
- lc->lconn_ber = NULLBER;
-
- /* message id */
- if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
- ber_free( ber, 1 );
- LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
- return( NSLDAPI_RESULT_ERROR );
- }
-
- /* if it's been abandoned, toss it */
- if ( ldap_abandoned( ld, (int)id ) ) {
- ber_free( ber, 1 );
- return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */
- }
-
- if ( id == LDAP_RES_UNSOLICITED ) {
- lr = NULL;
- } else if (( lr = nsldapi_find_request_by_msgid( ld, id )) == NULL ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "no request for response with msgid %d (tossing)\n",
- id, 0, 0 );
- ber_free( ber, 1 );
- return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */
- }
-
- /* the message type */
- if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
- ber_free( ber, 1 );
- LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
- return( NSLDAPI_RESULT_ERROR );
- }
- LDAPDebug( LDAP_DEBUG_TRACE, "got %s msgid %d, original id %d\n",
- ( tag == LDAP_RES_SEARCH_ENTRY ) ? "ENTRY" :
- ( tag == LDAP_RES_SEARCH_REFERENCE ) ? "REFERENCE" : "RESULT", id,
- ( lr == NULL ) ? id : lr->lr_origid );
-
- if ( lr != NULL ) {
- id = lr->lr_origid;
- lr->lr_res_msgtype = tag;
- }
- rc = NSLDAPI_RESULT_NOT_FOUND; /* default is to keep looking (no response found) */
-
- if ( id != LDAP_RES_UNSOLICITED && ( tag == LDAP_RES_SEARCH_REFERENCE ||
- tag != LDAP_RES_SEARCH_ENTRY )) {
- int refchasing, reftotal, simple_request = 0;
- LDAPControl **ctrls = NULL;
-
- check_for_refs( ld, lr, ber, lc->lconn_version, &reftotal,
- &refchasing );
-
- if ( refchasing > 0 || lr->lr_outrefcnt > 0 ) {
- /*
- * we're chasing one or more new refs...
- */
- ber_free( ber, 1 );
- ber = NULLBER;
- lr->lr_status = LDAP_REQST_CHASINGREFS;
- message_can_be_returned = 0;
-
- } else if ( tag != LDAP_RES_SEARCH_REFERENCE ) {
- /*
- * this request is complete...
- */
- has_parent = ( lr->lr_parent != NULL );
-
- if ( lr->lr_outrefcnt <= 0 && !has_parent ) {
- /* request without any refs */
- simple_request = ( reftotal == 0 );
- }
-
- /*
- * If this is not a child request and it is a bind
- * request, reset the connection's bind DN and
- * status based on the result of the operation.
- */
- if ( !has_parent &&
- LDAP_RES_BIND == lr->lr_res_msgtype &&
- lr->lr_conn != NULL ) {
- if ( lr->lr_conn->lconn_binddn != NULL ) {
- NSLDAPI_FREE(
- lr->lr_conn->lconn_binddn );
- }
- if ( LDAP_SUCCESS == nsldapi_parse_result( ld,
- lr->lr_res_msgtype, ber, &lderr, NULL,
- NULL, NULL, NULL )
- && LDAP_SUCCESS == lderr ) {
- lr->lr_conn->lconn_bound = 1;
- lr->lr_conn->lconn_binddn =
- lr->lr_binddn;
- lr->lr_binddn = NULL;
- } else {
- lr->lr_conn->lconn_bound = 0;
- lr->lr_conn->lconn_binddn = NULL;
- }
- }
-
- /*
- * if this response is to a child request, we toss
- * the message contents and just merge error info.
- * into the parent.
- */
- if ( has_parent ) {
- /* Extract any response controls from ber before ditching it */
- if( nsldapi_find_controls( ber, &ctrls ) != LDAP_SUCCESS ) {
- ber_free( ber, 1 );
- LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
- return( NSLDAPI_RESULT_ERROR );
- }
-
- ber_free( ber, 1 );
- ber = NULLBER;
- }
- while ( lr->lr_parent != NULL ) {
- merge_error_info( ld, lr->lr_parent, lr );
-
- lr = lr->lr_parent;
- --lr->lr_outrefcnt;
- if ( !NSLDAPI_REQUEST_COMPLETE(lr)) {
- break;
- }
- }
- /* Stash response controls in original request so they can be baked
- into the manufactured result message later */
- if( ctrls != NULL ) {
- if( lr->lr_res_ctrls != NULL ) {
- /* There are controls saved in original request already,
- replace them with the new ones because we only save
- the final controls received.
- May want to arrange for merging intermediate response
- controls into the array in the future */
- ldap_controls_free( lr->lr_res_ctrls );
- }
- lr->lr_res_ctrls = ctrls;
- }
-
- /*
- * we recognize a request as fully complete when:
- * 1) it is not a child request (NULL parent)
- * 2) it has no outstanding referrals
- * 3) we have received a result for the request (i.e.,
- * something other than an entry or a reference).
- */
- if ( lr->lr_parent == NULL
- && NSLDAPI_REQUEST_COMPLETE(lr)) {
- id = lr->lr_msgid;
- tag = lr->lr_res_msgtype;
- LDAPDebug( LDAP_DEBUG_TRACE,
- "request %d done\n", id, 0, 0 );
-LDAPDebug( LDAP_DEBUG_TRACE,
-"res_errno: %d, res_error: <%s>, res_matched: <%s>\n",
-lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
-lr->lr_res_matched ? lr->lr_res_matched : "" );
- if ( !simple_request ) {
- if ( ber != NULLBER ) {
- ber_free( ber, 1 );
- ber = NULLBER;
- }
- if ( build_result_ber( ld, &ber, lr )
- != LDAP_SUCCESS ) {
- rc = NSLDAPI_RESULT_ERROR;
- } else {
- manufactured_result = 1;
- }
- }
-
- nsldapi_free_request( ld, lr, 1 );
- /* Since we asked nsldapi_free_request() to free the
- connection, lets make sure our callers know it's gone. */
- *lcp = NULL;
- } else {
- message_can_be_returned = 0;
- }
- }
- }
-
- if ( ber == NULLBER ) {
- return( rc );
- }
-
- /* make a new ldap message */
- if ( (new = (LDAPMessage*)NSLDAPI_CALLOC( 1, sizeof(struct ldapmsg) ))
- == NULL ) {
- LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
- return( NSLDAPI_RESULT_ERROR );
- }
- new->lm_msgid = (int)id;
- new->lm_msgtype = tag;
- new->lm_ber = ber;
-
- /*
- * if this is a search entry or if this request is complete (i.e.,
- * there are no outstanding referrals) then add to cache and check
- * to see if we should return this to the caller right away or not.
- */
- if ( message_can_be_returned ) {
- if ( ld->ld_cache_on ) {
- nsldapi_add_result_to_cache( ld, new );
- }
-
- if ( msgid == LDAP_RES_ANY || id == msgid ) {
- if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT ) {
- /*
- * return the first response we have for this
- * search request later (possibly an entire
- * chain of messages).
- */
- foundit = 1;
- } else if ( all == 0
- || (new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE
- && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) {
- *result = new;
- LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL,
- NULL );
- return( tag );
- }
- }
- }
-
- /*
- * if not, we must add it to the list of responses. if
- * the msgid is already there, it must be part of an existing
- * search response.
- */
-
- prev = NULL;
- LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK );
- for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {
- if ( l->lm_msgid == new->lm_msgid )
- break;
- prev = l;
- }
-
- /* not part of an existing search response */
- if ( l == NULL ) {
- if ( foundit ) {
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- *result = new;
- LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL );
- return( tag );
- }
-
- new->lm_next = ld->ld_responses;
- ld->ld_responses = new;
- LDAPDebug( LDAP_DEBUG_TRACE,
- "adding new response id %d type %d (looking for id %d)\n",
- new->lm_msgid, new->lm_msgtype, msgid );
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- if( message_can_be_returned )
- POST( ld, new->lm_msgid, new );
- return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */
- }
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "adding response 0x%p - id %d type %d",
- new, new->lm_msgid, new->lm_msgtype );
- LDAPDebug( LDAP_DEBUG_TRACE, " (looking for id %d)\n", msgid, 0, 0 );
-
- /*
- * part of a search response - add to end of list of entries
- *
- * the first step is to find the end of the list of entries and
- * references. after the following loop is executed, tmp points to
- * the last entry or reference in the chain. If there are none,
- * tmp points to the search result.
- */
- chainprev = NULL;
- for ( tmp = l; tmp->lm_chain != NULL &&
- ( tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY
- || tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE );
- tmp = tmp->lm_chain ) {
- chainprev = tmp;
- }
-
- /*
- * If this is a manufactured result message and a result is already
- * queued we throw away the one that is queued and replace it with
- * our new result. This is necessary so we don't end up returning
- * more than one result.
- */
- if ( manufactured_result &&
- tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) {
- /*
- * the result is the only thing in the chain... replace it.
- */
- new->lm_chain = tmp->lm_chain;
- new->lm_next = tmp->lm_next;
- if ( chainprev == NULL ) {
- if ( prev == NULL ) {
- ld->ld_responses = new;
- } else {
- prev->lm_next = new;
- }
- } else {
- chainprev->lm_chain = new;
- }
- if ( l == tmp ) {
- l = new;
- }
- ldap_msgfree( tmp );
-
- } else if ( manufactured_result && tmp->lm_chain != NULL
- && tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT ) {
- /*
- * entries or references are also present, so the result
- * is the next entry after tmp. replace it.
- */
- new->lm_chain = tmp->lm_chain->lm_chain;
- new->lm_next = tmp->lm_chain->lm_next;
- ldap_msgfree( tmp->lm_chain );
- tmp->lm_chain = new;
-
- } else if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) {
- /*
- * the result is the only thing in the chain... add before it.
- */
- new->lm_chain = tmp;
- if ( chainprev == NULL ) {
- if ( prev == NULL ) {
- ld->ld_responses = new;
- } else {
- prev->lm_next = new;
- }
- } else {
- chainprev->lm_chain = new;
- }
- if ( l == tmp ) {
- l = new;
- }
-
- } else {
- /*
- * entries and/or references are present... add to the end
- * of the entry/reference part of the chain.
- */
- new->lm_chain = tmp->lm_chain;
- tmp->lm_chain = new;
- }
-
- /*
- * return the first response or the whole chain if that's what
- * we were looking for....
- */
- if ( foundit ) {
- if ( all == 0 && l->lm_chain != NULL ) {
- /*
- * only return the first response in the chain
- */
- if ( prev == NULL ) {
- ld->ld_responses = l->lm_chain;
- } else {
- prev->lm_next = l->lm_chain;
- }
- l->lm_chain = NULL;
- tag = l->lm_msgtype;
- } else {
- /*
- * return all of the responses (may be a chain)
- */
- if ( prev == NULL ) {
- ld->ld_responses = l->lm_next;
- } else {
- prev->lm_next = l->lm_next;
- }
- }
- *result = l;
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL );
- return( tag );
- }
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */
-}
-
-
-/*
- * check for LDAPv2+ (UMich extension) or LDAPv3 referrals or references
- * errors are merged in "lr".
- */
-static void
-check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber,
- int ldapversion, int *totalcountp, int *chasingcountp )
-{
- int err, origerr;
- char *errstr, *matcheddn, **v3refs;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "check_for_refs\n", 0, 0, 0 );
-
- *chasingcountp = *totalcountp = 0;
-
- if ( ldapversion < LDAP_VERSION2 || ( lr->lr_parent == NULL
- && ( ld->ld_options & LDAP_BITOPT_REFERRALS ) == 0 )) {
- /* referrals are not supported or are disabled */
- return;
- }
-
- if ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
- err = nsldapi_parse_reference( ld, ber, &v3refs, NULL );
- origerr = LDAP_REFERRAL; /* a small lie... */
- matcheddn = errstr = NULL;
- } else {
- err = nsldapi_parse_result( ld, lr->lr_res_msgtype, ber,
- &origerr, &matcheddn, &errstr, &v3refs, NULL );
- }
-
- if ( err != LDAP_SUCCESS ) {
- /* parse failed */
- return;
- }
-
- if ( origerr == LDAP_REFERRAL ) { /* ldapv3 */
- if ( v3refs != NULL ) {
- err = nsldapi_chase_v3_refs( ld, lr, v3refs,
- ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ),
- totalcountp, chasingcountp );
- ldap_value_free( v3refs );
- }
- } else if ( ldapversion == LDAP_VERSION2
- && origerr != LDAP_SUCCESS ) {
- /* referrals may be present in the error string */
- err = nsldapi_chase_v2_referrals( ld, lr, &errstr,
- totalcountp, chasingcountp );
- }
-
- /* set LDAP errno, message, and matched string appropriately */
- if ( lr->lr_res_error != NULL ) {
- NSLDAPI_FREE( lr->lr_res_error );
- }
- lr->lr_res_error = errstr;
-
- if ( lr->lr_res_matched != NULL ) {
- NSLDAPI_FREE( lr->lr_res_matched );
- }
- lr->lr_res_matched = matcheddn;
-
- if ( err == LDAP_SUCCESS && ( *chasingcountp == *totalcountp )) {
- if ( *totalcountp > 0 && ( origerr == LDAP_PARTIAL_RESULTS
- || origerr == LDAP_REFERRAL )) {
- /* substitute success for referral error codes */
- lr->lr_res_errno = LDAP_SUCCESS;
- } else {
- /* preserve existing non-referral error code */
- lr->lr_res_errno = origerr;
- }
- } else if ( err != LDAP_SUCCESS ) {
- /* error occurred while trying to chase referrals */
- lr->lr_res_errno = err;
- } else {
- /* some referrals were not recognized */
- lr->lr_res_errno = ( ldapversion == LDAP_VERSION2 )
- ? LDAP_PARTIAL_RESULTS : LDAP_REFERRAL;
- }
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "check_for_refs: new result: msgid %d, res_errno %d, ",
- lr->lr_msgid, lr->lr_res_errno, 0 );
- LDAPDebug( LDAP_DEBUG_TRACE, " res_error <%s>, res_matched <%s>\n",
- lr->lr_res_error ? lr->lr_res_error : "",
- lr->lr_res_matched ? lr->lr_res_matched : "", 0 );
- LDAPDebug( LDAP_DEBUG_TRACE,
- "check_for_refs: %d new refs(s); chasing %d of them\n",
- *totalcountp, *chasingcountp, 0 );
-}
-
-
-/* returns an LDAP error code and also sets it in LDAP * */
-static int
-build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr )
-{
- ber_len_t len;
- ber_int_t along;
- BerElement *ber;
- int err;
-
- if (( err = nsldapi_alloc_ber_with_options( ld, &ber ))
- != LDAP_SUCCESS ) {
- return( err );
- }
- *berp = ber;
- if ( ber_printf( ber, lr->lr_res_ctrls ? "{it{ess}" : "{it{ess}}",
- lr->lr_msgid, (long)lr->lr_res_msgtype, lr->lr_res_errno,
- lr->lr_res_matched ? lr->lr_res_matched : "",
- lr->lr_res_error ? lr->lr_res_error : "" ) == -1 ) {
- return( LDAP_ENCODING_ERROR );
- }
-
- if ( NULL != lr->lr_res_ctrls && nsldapi_put_controls( ld,
- lr->lr_res_ctrls, 1 /* close seq */, ber ) != LDAP_SUCCESS ) {
- return( LDAP_ENCODING_ERROR );
- }
-
- ber_reset( ber, 1 );
- if ( ber_skip_tag( ber, &len ) == LBER_ERROR ||
- ber_get_int( ber, &along ) == LBER_ERROR ||
- ber_peek_tag( ber, &len ) == LBER_ERROR ) {
- return( LDAP_DECODING_ERROR );
- }
-
- return( LDAP_SUCCESS );
-}
-
-
-static void
-merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )
-{
-/*
- * Merge error information in "lr" with "parentr" error code and string.
- */
- if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) {
- parentr->lr_res_errno = lr->lr_res_errno;
- if ( lr->lr_res_error != NULL ) {
- (void)nsldapi_append_referral( ld, &parentr->lr_res_error,
- lr->lr_res_error );
- }
- } else if ( lr->lr_res_errno != LDAP_SUCCESS &&
- parentr->lr_res_errno == LDAP_SUCCESS ) {
- parentr->lr_res_errno = lr->lr_res_errno;
- if ( parentr->lr_res_error != NULL ) {
- NSLDAPI_FREE( parentr->lr_res_error );
- }
- parentr->lr_res_error = lr->lr_res_error;
- lr->lr_res_error = NULL;
- if ( NAME_ERROR( lr->lr_res_errno )) {
- if ( parentr->lr_res_matched != NULL ) {
- NSLDAPI_FREE( parentr->lr_res_matched );
- }
- parentr->lr_res_matched = lr->lr_res_matched;
- lr->lr_res_matched = NULL;
- }
- }
-
- LDAPDebug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ",
- parentr->lr_msgid, 0, 0 );
- LDAPDebug( LDAP_DEBUG_TRACE, "result lderrno %d, error <%s>, matched <%s>\n",
- parentr->lr_res_errno, parentr->lr_res_error ?
- parentr->lr_res_error : "", parentr->lr_res_matched ?
- parentr->lr_res_matched : "" );
-}
-
-#if defined( CLDAP )
-#if !defined( macintosh ) && !defined( DOS ) && !defined( _WINDOWS ) && !defined(XP_OS2)
-/* XXXmcs: was revised to support extended I/O callbacks but never compiled! */
-static int
-cldap_select1( LDAP *ld, struct timeval *timeout )
-{
- int rc;
- static int tblsize = 0;
- NSLDAPIIOStatus *iosp = ld->ld_iostatus;
-
- if ( tblsize == 0 ) {
-#ifdef USE_SYSCONF
- tblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
- tblsize = getdtablesize();
-#endif /* USE_SYSCONF */
- }
-
- if ( tblsize >= FD_SETSIZE ) {
- /*
- * clamp value so we don't overrun the fd_set structure
- */
- tblsize = FD_SETSIZE - 1;
- }
-
- if ( NSLDAPI_IOSTATUS_TYPE_OSNATIVE == iosp->ios_type ) {
- fd_set readfds;
-
- FD_ZERO( &readfds );
- FD_SET( ld->ld_sbp->sb_sd, &readfds );
-
- /* XXXmcs: UNIX platforms should use poll() */
- rc = select( tblsize, &readfds, 0, 0, timeout ) );
-
- } else if ( NSLDAPI_IOSTATUS_TYPE_CALLBACK == iosp->ios_type ) {
- LDAP_X_PollFD pollfds[ 1 ];
-
- pollfds[0].lpoll_fd = ld->ld_sbp->sb_sd;
- pollfds[0].lpoll_arg = ld->ld_sbp->sb_arg;
- pollfds[0].lpoll_events = LDAP_X_POLLIN;
- pollfds[0].lpoll_revents = 0;
- rc = ld->ld_extpoll_fn( pollfds, 1, nsldapi_tv2ms( timeout ),
- ld->ld_ext_session_arg );
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "nsldapi_iostatus_poll: unknown I/O type %d\n",
- rc = 0; /* simulate a timeout (what else to do?) */
- }
-
- return( rc );
-}
-#endif /* !macintosh */
-
-
-#ifdef macintosh
-static int
-cldap_select1( LDAP *ld, struct timeval *timeout )
-{
- /* XXXmcs: needs to be revised to support I/O callbacks */
- return( tcpselect( ld->ld_sbp->sb_sd, timeout ));
-}
-#endif /* macintosh */
-
-
-#if (defined( DOS ) && defined( WINSOCK )) || defined( _WINDOWS ) || defined(XP_OS2)
-/* XXXmcs: needs to be revised to support extended I/O callbacks */
-static int
-cldap_select1( LDAP *ld, struct timeval *timeout )
-{
- fd_set readfds;
- int rc;
-
- FD_ZERO( &readfds );
- FD_SET( ld->ld_sbp->sb_sd, &readfds );
-
- if ( NSLDAPI_IO_TYPE_STANDARD == ld->ldiou_type &&
- NULL != ld->ld_select_fn ) {
- rc = ld->ld_select_fn( 1, &readfds, 0, 0, timeout );
- } else if ( NSLDAPI_IO_TYPE_EXTENDED == ld->ldiou_type &&
- NULL != ld->ld_extselect_fn ) {
- rc = ld->ld_extselect_fn( ld->ld_ext_session_arg, 1, &readfds, 0,
- 0, timeout ) );
- } else {
- /* XXXmcs: UNIX platforms should use poll() */
- rc = select( 1, &readfds, 0, 0, timeout ) );
- }
-
- return( rc == SOCKET_ERROR ? -1 : rc );
-}
-#endif /* WINSOCK || _WINDOWS */
-#endif /* CLDAP */
-
-int
-LDAP_CALL
-ldap_msgfree( LDAPMessage *lm )
-{
- LDAPMessage *next;
- int type = 0;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 );
-
- for ( ; lm != NULL; lm = next ) {
- next = lm->lm_chain;
- type = lm->lm_msgtype;
- ber_free( lm->lm_ber, 1 );
- NSLDAPI_FREE( (char *) lm );
- }
-
- return( type );
-}
-
-/*
- * ldap_msgdelete - delete a message. It returns:
- * 0 if the entire message was deleted
- * -1 if the message was not found, or only part of it was found
- */
-int
-ldap_msgdelete( LDAP *ld, int msgid )
-{
- LDAPMessage *lm, *prev;
- int msgtype;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 );
-
- if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
- return( -1 ); /* punt */
- }
-
- prev = NULL;
- LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK );
- for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) {
- if ( lm->lm_msgid == msgid )
- break;
- prev = lm;
- }
-
- if ( lm == NULL )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
- return( -1 );
- }
-
- if ( prev == NULL )
- ld->ld_responses = lm->lm_next;
- else
- prev->lm_next = lm->lm_next;
- LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK );
-
- msgtype = ldap_msgfree( lm );
- if ( msgtype == LDAP_RES_SEARCH_ENTRY
- || msgtype == LDAP_RES_SEARCH_REFERENCE ) {
- return( -1 );
- }
-
- return( 0 );
-}
-
-
-/*
- * return 1 if message msgid is waiting to be abandoned, 0 otherwise
- */
-static int
-ldap_abandoned( LDAP *ld, int msgid )
-{
- int i;
-
- LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK );
- if ( ld->ld_abandoned == NULL )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( 0 );
- }
-
- for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
- if ( ld->ld_abandoned[i] == msgid )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( 1 );
- }
-
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( 0 );
-}
-
-
-static int
-ldap_mark_abandoned( LDAP *ld, int msgid )
-{
- int i;
-
- LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK );
- if ( ld->ld_abandoned == NULL )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( -1 );
- }
-
- for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
- if ( ld->ld_abandoned[i] == msgid )
- break;
-
- if ( ld->ld_abandoned[i] == -1 )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( -1 );
- }
-
- for ( ; ld->ld_abandoned[i] != -1; i++ ) {
- ld->ld_abandoned[i] = ld->ld_abandoned[i + 1];
- }
-
- LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
- return( 0 );
-}
-
-
-#ifdef CLDAP
-int
-cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement **ber )
-{
- int rc;
- ber_tag_t tag;
- ber_len_t len;
-
- if ( ld->ld_sbp->sb_ber.ber_ptr >= ld->ld_sbp->sb_ber.ber_end ) {
- rc = cldap_select1( ld, timeout );
- if ( rc == -1 || rc == 0 ) {
- LDAP_SET_LDERRNO( ld, (rc == -1 ? LDAP_SERVER_DOWN :
- LDAP_TIMEOUT), NULL, NULL );
- return( rc );
- }
- }
-
- /* get the next message */
- if ( (tag = ber_get_next( ld->ld_sbp, &len, ber ))
- != LDAP_TAG_MESSAGE ) {
- LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
- LDAP_LOCAL_ERROR), NULL, NULL );
- return( -1 );
- }
-
- return( tag );
-}
-#endif /* CLDAP */
-
-int
-nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result )
-{
- LDAPPend *lp;
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "nsldapi_post_result(ld=0x%p, msgid=%d, result=0x%p)\n",
- ld, msgid, result );
- LDAP_MUTEX_LOCK( ld, LDAP_PEND_LOCK );
- if( msgid == LDAP_RES_ANY ) {
- /*
- * Look for any pending request for which someone is waiting.
- */
- for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next )
- {
- if ( lp->lp_sema != NULL ) {
- break;
- }
- }
- /*
- * If we did't find a pending request, lp is NULL at this
- * point, and we will leave this function without doing
- * anything more -- which is exactly what we want to do.
- */
- }
- else
- {
- /*
- * Look for a pending request specific to this message id
- */
- for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next )
- {
- if( lp->lp_msgid == msgid )
- break;
- }
-
- if( lp == NULL )
- {
- /*
- * No pending requests for this response... append to
- * our pending result list.
- */
- LDAPPend *newlp;
- newlp = (LDAPPend *)NSLDAPI_CALLOC( 1,
- sizeof( LDAPPend ));
- if( newlp == NULL )
- {
- LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK );
- LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL,
- NULL );
- return (-1);
- }
- newlp->lp_msgid = msgid;
- newlp->lp_result = result;
- link_pend( ld, newlp );
- }
- }
-
-
- if( lp != NULL )
- {
- /*
- * Wake up a thread that is waiting for this result.
- */
- lp->lp_msgid = msgid;
- lp->lp_result = result;
- LDAP_SEMA_POST( ld, lp );
- }
-
- LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK );
- return (0);
-}
-
-static void
-link_pend( LDAP *ld, LDAPPend *lp )
-{
- if (( lp->lp_next = ld->ld_pend ) != NULL )
- {
- lp->lp_next->lp_prev = lp;
- }
- ld->ld_pend = lp;
- lp->lp_prev = NULL;
-}