version 1.36, 1999/07/13 04:39:55
|
version 1.36.2.12, 2001/03/15 03:20:03
|
Line 1
|
Line 1
|
|
/* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.36.2.11 2001/01/17 04:36:27 kurt Exp $ */ |
/* |
/* |
* Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. |
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. |
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file |
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file |
*/ |
*/ |
/* Portions |
/* Portions |
* Copyright (c) 1990 Regents of the University of Michigan. |
* Copyright (c) 1990 Regents of the University of Michigan. |
* All rights reserved. |
* All rights reserved. |
|
*/ |
|
/*--- |
|
* This notice applies to changes, created by or for Novell, Inc., |
|
* to preexisting works for which notices appear elsewhere in this file. |
|
* |
|
* Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. |
|
* |
|
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. |
|
* USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION |
|
* 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT |
|
* HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE |
|
* TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS |
|
* WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC |
|
* LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE |
|
* PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. |
|
*--- |
|
* Modification to OpenLDAP source by Novell, Inc. |
|
* April 2000 sfs Add code to process V3 referrals and search results |
* |
* |
* result.c - wait for an ldap result |
* result.c - wait for an ldap result |
*/ |
*/ |
Line 44 static ber_tag_t try_read1msg LDAP_P(( L
|
Line 63 static ber_tag_t try_read1msg LDAP_P(( L
|
int all, Sockbuf *sb, LDAPConn *lc, LDAPMessage **result )); |
int all, Sockbuf *sb, LDAPConn *lc, LDAPMessage **result )); |
static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr )); |
static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr )); |
static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); |
static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); |
|
static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all)); |
|
|
|
|
/* |
/* |
* ldap_result - wait for an ldap result response to a message from the |
* 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 server. If msgid is LDAP_RES_ANY (-1), any message will be |
* ldap_result will wait for a response with msgid. If all is 0 the |
* accepted. If msgid is LDAP_RES_UNSOLICITED (0), any unsolicited |
* first message with id msgid will be accepted, otherwise, ldap_result |
* message is accepted. Otherwise ldap_result will wait for a response |
* will wait for all responses with id msgid and then return a pointer to |
* with msgid. If all is LDAP_MSG_ONE (0) the first message with id |
* the entire list of messages. This is only useful for search responses, |
* msgid will be accepted, otherwise, ldap_result will wait for all |
* which can be of two message types (zero or more entries, followed by an |
* responses with id msgid and then return a pointer to the entire list |
* ldap result). The type of the first message received is returned. |
* of messages. In general, this is only useful for search responses, |
|
* which can be of three message types (zero or more entries, zero or |
|
* search references, followed by an ldap result). An extension to |
|
* LDAPv3 allows partial extended responses to be returned in response |
|
* to any request. The type of the first message received is returned. |
* When waiting, any messages that have been abandoned are discarded. |
* When waiting, any messages that have been abandoned are discarded. |
* |
* |
* Example: |
* Example: |
Line 68 ldap_result(
|
Line 92 ldap_result(
|
struct timeval *timeout, |
struct timeval *timeout, |
LDAPMessage **result ) |
LDAPMessage **result ) |
{ |
{ |
LDAPMessage *lm, *lastlm, *nextlm; |
LDAPMessage *lm; |
|
|
assert( ld != NULL ); |
assert( ld != NULL ); |
assert( result != NULL ); |
assert( result != NULL ); |
|
|
Debug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, "ldap_result msgid %d\n", msgid, 0, 0 ); |
|
|
if( ld == NULL ) { |
if( ld == NULL ) { |
return -1; |
return -1; |
Line 84 ldap_result(
|
Line 108 ldap_result(
|
return -1; |
return -1; |
} |
} |
|
|
/* |
lm = chkResponseList(ld, msgid, all); |
* First, look through the list of responses we have received on |
|
|
if ( lm == NULL ) { |
|
return( wait4msg( ld, msgid, all, timeout, result ) ); |
|
} |
|
|
|
*result = lm; |
|
ld->ld_errno = LDAP_SUCCESS; |
|
return( lm->lm_msgtype ); |
|
} |
|
|
|
static LDAPMessage * |
|
chkResponseList( |
|
LDAP *ld, |
|
int msgid, |
|
int all) |
|
{ |
|
LDAPMessage *lm, *lastlm, *nextlm; |
|
/* |
|
* Look through the list of responses we have received on |
* this association and see if the response we're interested in |
* this association and see if the response we're interested in |
* is there. If it is, return it. If not, call wait4msg() to |
* is there. If it is, return it. If not, call wait4msg() to |
* wait until it arrives or timeout occurs. |
* wait until it arrives or timeout occurs. |
*/ |
*/ |
|
|
*result = NULL; |
Debug( LDAP_DEBUG_TRACE, |
|
"ldap_chkResponseList for msgid=%d, all=%d\n", |
|
msgid, all, 0 ); |
lastlm = NULL; |
lastlm = NULL; |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
nextlm = lm->lm_next; |
nextlm = lm->lm_next; |
|
|
if ( ldap_abandoned( ld, lm->lm_msgid ) ) { |
if ( ldap_abandoned( ld, lm->lm_msgid ) ) { |
|
Debug( LDAP_DEBUG_TRACE, |
|
"ldap_chkResponseList msg abandoned, msgid %d\n", |
|
msgid, 0, 0 ); |
ldap_mark_abandoned( ld, lm->lm_msgid ); |
ldap_mark_abandoned( ld, lm->lm_msgid ); |
|
|
if ( lastlm == NULL ) { |
if ( lastlm == NULL ) { |
|
/* Remove first entry in list */ |
ld->ld_responses = lm->lm_next; |
ld->ld_responses = lm->lm_next; |
} else { |
} else { |
lastlm->lm_next = nextlm; |
lastlm->lm_next = nextlm; |
Line 113 ldap_result(
|
Line 161 ldap_result(
|
if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { |
if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { |
LDAPMessage *tmp; |
LDAPMessage *tmp; |
|
|
if ( all == 0 |
if ( all == LDAP_MSG_ONE || msgid == LDAP_RES_UNSOLICITED ) { |
|| (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT |
|
&& lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE /* LDAPv3 */ |
|
&& lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) |
|
break; |
break; |
|
} |
|
|
for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { |
for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { |
if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) |
if ( tmp->lm_msgtype != LDAP_RES_SEARCH_ENTRY |
|
&& tmp->lm_msgtype != LDAP_RES_SEARCH_REFERENCE |
|
&& tmp->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL ) |
|
{ |
break; |
break; |
|
} |
} |
} |
|
|
if ( tmp == NULL ) { |
if ( tmp == NULL ) { |
Line 132 ldap_result(
|
Line 182 ldap_result(
|
} |
} |
lastlm = lm; |
lastlm = lm; |
} |
} |
if ( lm == NULL ) { |
|
return( wait4msg( ld, msgid, all, timeout, result ) ); |
|
} |
|
|
|
if ( lastlm == NULL ) { |
if ( lm != NULL ) { |
ld->ld_responses = (all == 0 && lm->lm_chain != NULL |
/* Found an entry, remove it from the list */ |
? lm->lm_chain : lm->lm_next); |
if ( lastlm == NULL ) { |
|
ld->ld_responses = (all == LDAP_MSG_ONE && lm->lm_chain != NULL |
|
? lm->lm_chain : lm->lm_next); |
|
} else { |
|
lastlm->lm_next = (all == LDAP_MSG_ONE && lm->lm_chain != NULL |
|
? lm->lm_chain : lm->lm_next); |
|
} |
|
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { |
|
lm->lm_chain->lm_next = lm->lm_next; |
|
lm->lm_chain = NULL; |
|
} |
|
lm->lm_next = NULL; |
|
} |
|
|
|
#ifdef LDAP_DEBUG |
|
if( lm == NULL) { |
|
Debug( LDAP_DEBUG_TRACE, |
|
"ldap_chkResponseList returns NULL\n", 0, 0, 0); |
} else { |
} else { |
lastlm->lm_next = (all == 0 && lm->lm_chain != NULL |
Debug( LDAP_DEBUG_TRACE, |
? lm->lm_chain : lm->lm_next); |
"ldap_chkResponseList returns msgid %d, type 0x%02lu\n", |
|
lm->lm_msgid, (unsigned long) lm->lm_msgtype, 0); |
} |
} |
if ( all == 0 ) |
#endif |
lm->lm_chain = NULL; |
return lm; |
lm->lm_next = NULL; |
|
|
|
*result = lm; |
|
ld->ld_errno = LDAP_SUCCESS; |
|
return( lm->lm_msgtype ); |
|
} |
} |
|
|
static int |
static int |
Line 171 wait4msg(
|
Line 231 wait4msg(
|
|
|
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
if ( timeout == NULL ) { |
if ( timeout == NULL ) { |
Debug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n", |
Debug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout), msgid %d\n", |
0, 0, 0 ); |
msgid, 0, 0 ); |
} else { |
} else { |
Debug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n", |
Debug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec), msgid %d\n", |
(long) timeout->tv_sec, (long) timeout->tv_usec, 0 ); |
(long) timeout->tv_sec, (long) timeout->tv_usec, msgid ); |
} |
} |
#endif /* LDAP_DEBUG */ |
#endif /* LDAP_DEBUG */ |
|
|
Line 190 wait4msg(
|
Line 250 wait4msg(
|
rc = -2; |
rc = -2; |
while ( rc == -2 ) { |
while ( rc == -2 ) { |
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
|
Debug( LDAP_DEBUG_TRACE, "wait4msg continue, msgid %d, all %d\n", |
|
msgid, all, 0 ); |
if ( ldap_debug & LDAP_DEBUG_TRACE ) { |
if ( ldap_debug & LDAP_DEBUG_TRACE ) { |
ldap_dump_connection( ld, ld->ld_conns, 1 ); |
ldap_dump_connection( ld, ld->ld_conns, 1 ); |
ldap_dump_requests_and_responses( ld ); |
ldap_dump_requests_and_responses( ld ); |
} |
} |
#endif /* LDAP_DEBUG */ |
#endif /* LDAP_DEBUG */ |
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { |
|
if ( ber_pvt_sb_data_ready(lc->lconn_sb) ) { |
|
rc = try_read1msg( ld, msgid, all, lc->lconn_sb, |
|
lc, result ); |
|
break; |
|
} |
|
} |
|
|
|
if ( lc == NULL ) { |
if( (*result = chkResponseList(ld, msgid, all)) != NULL ) { |
rc = do_ldap_select( ld, tvp ); |
rc = (*result)->lm_msgtype; |
|
} else { |
|
|
|
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { |
|
if ( ber_sockbuf_ctrl( lc->lconn_sb, |
|
LBER_SB_OPT_DATA_READY, NULL ) ) { |
|
rc = try_read1msg( ld, msgid, all, lc->lconn_sb, |
|
lc, result ); |
|
break; |
|
} |
|
} |
|
|
|
if ( lc == NULL ) { |
|
rc = do_ldap_select( ld, tvp ); |
|
|
|
|
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
if ( rc == -1 ) { |
if ( rc == -1 ) { |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"do_ldap_select returned -1: errno %d\n", |
"do_ldap_select returned -1: errno %d\n", |
errno, 0, 0 ); |
errno, 0, 0 ); |
} |
} |
#endif |
#endif |
|
|
if ( rc == 0 || ( rc == -1 && ( |
if ( rc == 0 || ( rc == -1 && ( |
!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) |
!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) |
|| errno != EINTR ))) |
|| errno != EINTR ))) |
{ |
{ |
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : |
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : |
LDAP_TIMEOUT); |
LDAP_TIMEOUT); |
return( rc ); |
return( rc ); |
} |
} |
|
|
if ( rc == -1 ) { |
if ( rc == -1 ) { |
rc = -2; /* select interrupted: loop */ |
rc = -2; /* select interrupted: loop */ |
} else { |
} else { |
rc = -2; |
rc = -2; |
for ( lc = ld->ld_conns; rc == -2 && lc != NULL; |
for ( lc = ld->ld_conns; rc == -2 && lc != NULL; |
lc = nextlc ) { |
lc = nextlc ) { |
nextlc = lc->lconn_next; |
nextlc = lc->lconn_next; |
if ( lc->lconn_status == |
if ( lc->lconn_status == |
LDAP_CONNST_CONNECTED && |
LDAP_CONNST_CONNECTED && |
ldap_is_read_ready( ld, |
ldap_is_read_ready( ld, |
lc->lconn_sb )) { |
lc->lconn_sb )) { |
rc = try_read1msg( ld, msgid, all, |
rc = try_read1msg( ld, msgid, all, |
lc->lconn_sb, lc, result ); |
lc->lconn_sb, lc, result ); |
} |
} |
} |
} |
} |
} |
|
} |
} |
} |
|
|
if ( rc == -2 && tvp != NULL ) { |
if ( rc == -2 && tvp != NULL ) { |
Line 266 try_read1msg(
|
Line 335 try_read1msg(
|
ber_int_t msgid, |
ber_int_t msgid, |
int all, |
int all, |
Sockbuf *sb, |
Sockbuf *sb, |
LDAPConn *lc, |
LDAPConn *lc, |
LDAPMessage **result ) |
LDAPMessage **result ) |
{ |
{ |
BerElement *ber; |
BerElement *ber; |
Line 275 try_read1msg(
|
Line 344 try_read1msg(
|
ber_tag_t tag; |
ber_tag_t tag; |
ber_len_t len; |
ber_len_t len; |
int foundit = 0; |
int foundit = 0; |
LDAPRequest *lr; |
LDAPRequest *lr, *tmplr; |
BerElement tmpber; |
BerElement tmpber; |
int rc, refer_cnt, hadref, simple_request; |
int rc, refer_cnt, hadref, simple_request; |
ber_int_t lderr; |
ber_int_t lderr; |
|
/* |
|
* v3ref = flag for V3 referral / search reference |
|
* 0 = not a ref, 1 = sucessfully chased ref, -1 = pass ref to application |
|
*/ |
|
int v3ref; |
|
|
assert( ld != NULL ); |
assert( ld != NULL ); |
assert( lc != NULL ); |
assert( lc != NULL ); |
|
|
Debug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, "read1msg: msgid %d, all %d\n", msgid, all, 0 ); |
|
|
if ( lc->lconn_ber == NULL ) { |
if ( lc->lconn_ber == NULL ) { |
lc->lconn_ber = ldap_alloc_ber_with_options(ld); |
lc->lconn_ber = ldap_alloc_ber_with_options(ld); |
Line 334 try_read1msg(
|
Line 408 try_read1msg(
|
/* if it's been abandoned, toss it */ |
/* if it's been abandoned, toss it */ |
if ( ldap_abandoned( ld, id ) ) { |
if ( ldap_abandoned( ld, id ) ) { |
ber_free( ber, 1 ); |
ber_free( ber, 1 ); |
|
Debug( LDAP_DEBUG_ANY, "abandoned\n", 0, 0, 0); |
return( -2 ); /* continue looking */ |
return( -2 ); /* continue looking */ |
} |
} |
|
|
if (( lr = ldap_find_request_by_msgid( ld, id )) == NULL ) { |
if (( lr = ldap_find_request_by_msgid( ld, id )) == NULL ) { |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, |
"no request for response with msgid %ld (tossing)\n", |
"no request for response with msgid %ld (tossing)\n", |
id, 0, 0 ); |
(long) id, 0, 0 ); |
ber_free( ber, 1 ); |
ber_free( ber, 1 ); |
return( -2 ); /* continue looking */ |
return( -2 ); /* continue looking */ |
} |
} |
Line 352 try_read1msg(
|
Line 427 try_read1msg(
|
return( -1 ); |
return( -1 ); |
} |
} |
|
|
Debug( LDAP_DEBUG_TRACE, "ldap_read: %s msgid %ld, original id %d\n", |
Debug( LDAP_DEBUG_TRACE, |
( tag == LDAP_RES_SEARCH_ENTRY ) ? "entry" : |
"ldap_read: message type %s msgid %ld, original id %ld\n", |
( tag == LDAP_RES_SEARCH_REFERENCE ) ? "reference" : "result", |
ldap_int_msgtype2str( tag ), |
id, lr->lr_origid ); |
(long) lr->lr_msgid, (long) lr->lr_origid ); |
|
|
id = lr->lr_origid; |
id = lr->lr_origid; |
refer_cnt = 0; |
refer_cnt = 0; |
Line 363 try_read1msg(
|
Line 438 try_read1msg(
|
rc = -2; /* default is to keep looking (no response found) */ |
rc = -2; /* default is to keep looking (no response found) */ |
lr->lr_res_msgtype = tag; |
lr->lr_res_msgtype = tag; |
|
|
if ( tag != LDAP_RES_SEARCH_ENTRY ) { |
/* |
|
* This code figures out if we are going to chase a |
|
* referral / search reference, or pass it back to the application |
|
*/ |
|
v3ref = 0; /* Assume not a V3 search reference or referral */ |
|
if( (tag != LDAP_RES_SEARCH_ENTRY) && (ld->ld_version > LDAP_VERSION2) ) { |
|
BerElement tmpber = *ber; /* struct copy */ |
|
char **refs = NULL; |
|
|
|
if( tag == LDAP_RES_SEARCH_REFERENCE) { |
|
/* This is a V3 search reference */ |
|
/* Assume we do not chase the reference, but pass it to application */ |
|
v3ref = -1; |
|
if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || |
|
(lr->lr_parent != NULL) ) |
|
{ |
|
/* Get the referral list */ |
|
if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) { |
|
rc = LDAP_DECODING_ERROR; |
|
} else { |
|
/* Note: refs arrary is freed by ldap_chase_v3referrals */ |
|
refer_cnt = ldap_chase_v3referrals( ld, lr, refs, |
|
1, &lr->lr_res_error, &hadref ); |
|
if ( refer_cnt > 0 ) { /* sucessfully chased reference */ |
|
/* If haven't got end search, set chasing referrals */ |
|
if( lr->lr_status != LDAP_REQST_COMPLETED) { |
|
lr->lr_status = LDAP_REQST_CHASINGREFS; |
|
Debug( LDAP_DEBUG_TRACE, |
|
"read1msg: search ref chased, mark request chasing refs, id = %d\n", |
|
lr->lr_msgid, 0, 0); |
|
} |
|
v3ref = 1; /* We sucessfully chased the reference */ |
|
} |
|
} |
|
} |
|
} else { |
|
/* Check for V3 referral */ |
|
ber_len_t len; |
|
if ( ber_scanf( &tmpber, "{iaa",/*}*/ &lderr, |
|
&lr->lr_res_matched, &lr->lr_res_error ) |
|
!= LBER_ERROR ) { |
|
/* Check if V3 referral */ |
|
if( ber_peek_tag( &tmpber, &len) == LDAP_TAG_REFERRAL ) { |
|
/* We have a V3 referral, assume we cannot chase it */ |
|
v3ref = -1; |
|
if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) |
|
|| (lr->lr_parent != NULL) ) |
|
{ |
|
v3ref = -1; /* Assume referral not chased and return it to app */ |
|
/* Get the referral list */ |
|
if( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) { |
|
rc = LDAP_DECODING_ERROR; |
|
lr->lr_status = LDAP_REQST_COMPLETED; |
|
Debug( LDAP_DEBUG_TRACE, |
|
"read1msg: referral decode error, mark request completed, id = %d\n", |
|
lr->lr_msgid, 0, 0); |
|
} else { |
|
/* Chase the referral |
|
* Note: refs arrary is freed by ldap_chase_v3referrals |
|
*/ |
|
refer_cnt = ldap_chase_v3referrals( ld, lr, refs, |
|
0, &lr->lr_res_error, &hadref ); |
|
lr->lr_status = LDAP_REQST_COMPLETED; |
|
Debug( LDAP_DEBUG_TRACE, |
|
"read1msg: referral chased, mark request completed, id = %d\n", |
|
lr->lr_msgid, 0, 0); |
|
if( refer_cnt > 0) { |
|
v3ref = 1; /* Referral successfully chased */ |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( lr->lr_res_matched != NULL ) { |
|
LDAP_FREE( lr->lr_res_matched ); |
|
lr->lr_res_matched = NULL; |
|
} |
|
if( lr->lr_res_error != NULL ) { |
|
LDAP_FREE( lr->lr_res_error ); |
|
lr->lr_res_error = NULL; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* All results that just return a status, i.e. don't return data |
|
* go through the following code. This code also chases V2 referrals |
|
* and checks if all referrals have been chased. |
|
*/ |
|
if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref > -1) ) { |
|
/* For a v3 search referral/reference, only come here if already chased it */ |
if ( ld->ld_version >= LDAP_VERSION2 && |
if ( ld->ld_version >= LDAP_VERSION2 && |
( lr->lr_parent != NULL || |
( lr->lr_parent != NULL || |
LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ) ) |
LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ) ) |
{ |
{ |
tmpber = *ber; /* struct copy */ |
tmpber = *ber; /* struct copy */ |
if ( ber_scanf( &tmpber, "{iaa}", &lderr, |
if ( v3ref == 1 ) { |
|
; /* V3 search reference or V3 referral sucessfully chased */ |
|
} else if ( ber_scanf( &tmpber, "{iaa}", &lderr, |
&lr->lr_res_matched, &lr->lr_res_error ) |
&lr->lr_res_matched, &lr->lr_res_error ) |
!= LBER_ERROR ) { |
!= LBER_ERROR ) { |
if ( lderr != LDAP_SUCCESS ) { |
if ( lderr != LDAP_SUCCESS ) { |
/* referrals are in error string */ |
/* referrals are in error string */ |
refer_cnt = ldap_chase_referrals( ld, lr, |
refer_cnt = ldap_chase_referrals( ld, lr, |
&lr->lr_res_error, &hadref ); |
&lr->lr_res_error, -1, &hadref ); |
|
lr->lr_status = LDAP_REQST_COMPLETED; |
|
Debug( LDAP_DEBUG_TRACE, |
|
"read1msg: V2 referral chased, mark request completed, id = %d\n", lr->lr_msgid, 0, 0); |
} |
} |
|
|
/* save errno, message, and matched string */ |
/* save errno, message, and matched string */ |
Line 404 Debug( LDAP_DEBUG_TRACE,
|
Line 574 Debug( LDAP_DEBUG_TRACE,
|
if ( refer_cnt < 0 ) { |
if ( refer_cnt < 0 ) { |
return( -1 ); /* fatal error */ |
return( -1 ); /* fatal error */ |
} |
} |
lr->lr_status = LDAP_REQST_CHASINGREFS; |
lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */ |
} else { |
} else { |
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { |
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { |
/* request without any referrals */ |
/* request without any referrals */ |
Line 415 Debug( LDAP_DEBUG_TRACE,
|
Line 585 Debug( LDAP_DEBUG_TRACE,
|
ber = NULL; |
ber = NULL; |
} |
} |
|
|
|
lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */ |
|
Debug( LDAP_DEBUG_TRACE, |
|
"read1msg: mark request completed, id = %d\n", lr->lr_msgid, 0, 0); |
while ( lr->lr_parent != NULL ) { |
while ( lr->lr_parent != NULL ) { |
merge_error_info( ld, lr->lr_parent, lr ); |
merge_error_info( ld, lr->lr_parent, lr ); |
|
|
Line 424 Debug( LDAP_DEBUG_TRACE,
|
Line 597 Debug( LDAP_DEBUG_TRACE,
|
} |
} |
} |
} |
|
|
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { |
/* Check if all requests are finished, lr is now parent */ |
|
for(tmplr=lr ; tmplr != NULL; tmplr=tmplr->lr_refnext) { |
|
if( tmplr->lr_status != LDAP_REQST_COMPLETED) { |
|
break; |
|
} |
|
} |
|
|
|
/* This is the parent request if the request has referrals */ |
|
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL && tmplr == NULL ) { |
id = lr->lr_msgid; |
id = lr->lr_msgid; |
tag = lr->lr_res_msgtype; |
tag = lr->lr_res_msgtype; |
Debug( LDAP_DEBUG_ANY, "request %ld done\n", |
Debug( LDAP_DEBUG_ANY, "request %ld done\n", |
id, 0, 0 ); |
(long) id, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"res_errno: %d, res_error: <%s>, res_matched: <%s>\n", |
"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_errno, lr->lr_res_error ? lr->lr_res_error : "", |
Line 473 lr->lr_res_matched ? lr->lr_res_matched
|
Line 654 lr->lr_res_matched ? lr->lr_res_matched
|
|
|
/* is this the one we're looking for? */ |
/* is this the one we're looking for? */ |
if ( msgid == LDAP_RES_ANY || id == msgid ) { |
if ( msgid == LDAP_RES_ANY || id == msgid ) { |
if ( all == 0 |
if ( all == LDAP_MSG_ONE |
|| (new->lm_msgtype != LDAP_RES_SEARCH_RESULT |
|| (new->lm_msgtype != LDAP_RES_SEARCH_RESULT |
&& new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) { |
&& new->lm_msgtype != LDAP_RES_SEARCH_ENTRY |
|
&& new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) ) { |
*result = new; |
*result = new; |
ld->ld_errno = LDAP_SUCCESS; |
ld->ld_errno = LDAP_SUCCESS; |
return( tag ); |
return( tag ); |
Line 510 lr->lr_res_matched ? lr->lr_res_matched
|
Line 692 lr->lr_res_matched ? lr->lr_res_matched
|
return( -2 ); /* continue looking */ |
return( -2 ); /* continue looking */ |
} |
} |
|
|
Debug( LDAP_DEBUG_TRACE, "adding response id %d type %d:\n", |
Debug( LDAP_DEBUG_TRACE, "adding response id %ld type %ld:\n", |
new->lm_msgid, new->lm_msgtype, 0 ); |
(long) new->lm_msgid, (long) new->lm_msgtype, 0 ); |
|
|
/* part of a search response - add to end of list of entries */ |
/* part of a search response - add to end of list of entries */ |
for ( tmp = l; tmp->lm_chain != 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_ENTRY) || |
|
(tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) || |
|
(tmp->lm_chain->lm_msgtype == LDAP_RES_EXTENDED_PARTIAL )); |
tmp = tmp->lm_chain ) |
tmp = tmp->lm_chain ) |
; /* NULL */ |
; /* NULL */ |
tmp->lm_chain = new; |
tmp->lm_chain = new; |
Line 642 int
|
Line 826 int
|
ldap_msgtype( LDAPMessage *lm ) |
ldap_msgtype( LDAPMessage *lm ) |
{ |
{ |
assert( lm != NULL ); |
assert( lm != NULL ); |
return ( lm == NULL ) ? lm->lm_msgtype : -1; |
return ( lm != NULL ) ? lm->lm_msgtype : -1; |
} |
} |
|
|
|
|
Line 651 ldap_msgid( LDAPMessage *lm )
|
Line 835 ldap_msgid( LDAPMessage *lm )
|
{ |
{ |
assert( lm != NULL ); |
assert( lm != NULL ); |
|
|
return ( lm == NULL ) ? lm->lm_msgid : -1; |
return ( lm != NULL ) ? lm->lm_msgid : -1; |
} |
} |
|
|
|
|
|
char * ldap_int_msgtype2str( ber_tag_t tag ) |
|
{ |
|
switch( tag ) { |
|
case LDAP_RES_ADD: return "add"; |
|
case LDAP_RES_BIND: return "bind"; |
|
case LDAP_RES_COMPARE: return "compare"; |
|
case LDAP_RES_DELETE: return "delete"; |
|
case LDAP_RES_EXTENDED: return "extended-result"; |
|
case LDAP_RES_EXTENDED_PARTIAL: return "extended-partial"; |
|
case LDAP_RES_MODIFY: return "modify"; |
|
case LDAP_RES_RENAME: return "rename"; |
|
case LDAP_RES_SEARCH_ENTRY: return "search-entry"; |
|
case LDAP_RES_SEARCH_REFERENCE: return "search-reference"; |
|
case LDAP_RES_SEARCH_RESULT: return "search-result"; |
|
} |
|
return "unknown"; |
|
} |
|
|
int |
int |
ldap_msgfree( LDAPMessage *lm ) |
ldap_msgfree( LDAPMessage *lm ) |
{ |
{ |
LDAPMessage *next; |
LDAPMessage *next; |
int type = 0; |
int type = 0; |
|
|
assert( lm != NULL ); |
|
|
|
Debug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); |
|
|
for ( ; lm != NULL; lm = next ) { |
for ( ; lm != NULL; lm = next ) { |
Line 751 ldap_mark_abandoned( LDAP *ld, ber_int_t
|
Line 951 ldap_mark_abandoned( LDAP *ld, ber_int_t
|
|
|
return( 0 ); |
return( 0 ); |
} |
} |
|
|
|
|
#ifdef LDAP_CONNECTIONLESS |
|
int |
|
cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ) |
|
{ |
|
int rc; |
|
ber_tag_t tag; |
|
ber_len_t len; |
|
|
|
if ( ! ber_pvt_sb_data_ready(&ld->ld_sb) ) { |
|
/* restored from ldap_select1() in result.c version 1.24 */ |
|
fd_set readfds; |
|
if ( ldap_int_tblsize == 0 ) |
|
ldap_int_ip_init(); |
|
FD_ZERO( &readfds ); |
|
FD_SET( ber_pvt_sb_get_desc(&ld->ld_sb), &readfds ); |
|
rc = select( ldap_int_tblsize, &readfds, 0, 0, timeout ); |
|
|
|
if ( rc == -1 || rc == 0 ) { |
|
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : |
|
LDAP_TIMEOUT); |
|
return( rc ); |
|
} |
|
} |
|
|
|
/* get the next message */ |
|
if ( (tag = ber_get_next( &ld->ld_sb, &len, ber )) |
|
!= LDAP_TAG_MESSAGE ) { |
|
ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : |
|
LDAP_LOCAL_ERROR); |
|
return( -1 ); |
|
} |
|
|
|
return( 0 ); |
|
} |
|
#endif /* LDAP_CONNECTIONLESS */ |
|