1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public License 11*7c478bd9Sstevel@tonic-gate * Version 1.0 (the "NPL"); you may not use this file except in 12*7c478bd9Sstevel@tonic-gate * compliance with the NPL. You may obtain a copy of the NPL at 13*7c478bd9Sstevel@tonic-gate * http://www.mozilla.org/NPL/ 14*7c478bd9Sstevel@tonic-gate * 15*7c478bd9Sstevel@tonic-gate * Software distributed under the NPL is distributed on an "AS IS" basis, 16*7c478bd9Sstevel@tonic-gate * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL 17*7c478bd9Sstevel@tonic-gate * for the specific language governing rights and limitations under the 18*7c478bd9Sstevel@tonic-gate * NPL. 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * The Initial Developer of this code under the NPL is Netscape 21*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 22*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998 Netscape Communications Corporation. All Rights 23*7c478bd9Sstevel@tonic-gate * Reserved. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 27*7c478bd9Sstevel@tonic-gate * All rights reserved. 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * result.c - wait for an ldap result 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #if 0 34*7c478bd9Sstevel@tonic-gate #ifndef lint 35*7c478bd9Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; 36*7c478bd9Sstevel@tonic-gate #endif 37*7c478bd9Sstevel@tonic-gate #endif 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include "ldap-int.h" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 42*7c478bd9Sstevel@tonic-gate /* high resolution timer usage */ 43*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 44*7c478bd9Sstevel@tonic-gate #endif 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate static int check_response_queue( LDAP *ld, int msgid, int all, 47*7c478bd9Sstevel@tonic-gate int do_abandon_check, LDAPMessage **result ); 48*7c478bd9Sstevel@tonic-gate static int ldap_abandoned( LDAP *ld, int msgid ); 49*7c478bd9Sstevel@tonic-gate static int ldap_mark_abandoned( LDAP *ld, int msgid ); 50*7c478bd9Sstevel@tonic-gate static int wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, 51*7c478bd9Sstevel@tonic-gate struct timeval *timeout, LDAPMessage **result ); 52*7c478bd9Sstevel@tonic-gate static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc, 53*7c478bd9Sstevel@tonic-gate LDAPMessage **result ); 54*7c478bd9Sstevel@tonic-gate static void check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, 55*7c478bd9Sstevel@tonic-gate int ldapversion, int *totalcountp, int *chasingcountp ); 56*7c478bd9Sstevel@tonic-gate static int build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ); 57*7c478bd9Sstevel@tonic-gate static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ); 58*7c478bd9Sstevel@tonic-gate #if defined( CLDAP ) 59*7c478bd9Sstevel@tonic-gate static int cldap_select1( LDAP *ld, struct timeval *timeout ); 60*7c478bd9Sstevel@tonic-gate #endif 61*7c478bd9Sstevel@tonic-gate static void link_pend( LDAP *ld, LDAPPend *lp ); 62*7c478bd9Sstevel@tonic-gate #if 0 /* these functions are no longer used */ 63*7c478bd9Sstevel@tonic-gate static void unlink_pend( LDAP *ld, LDAPPend *lp ); 64*7c478bd9Sstevel@tonic-gate static int unlink_msg( LDAP *ld, int msgid, int all ); 65*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate /* 68*7c478bd9Sstevel@tonic-gate * ldap_result - wait for an ldap result response to a message from the 69*7c478bd9Sstevel@tonic-gate * ldap server. If msgid is -1, any message will be accepted, otherwise 70*7c478bd9Sstevel@tonic-gate * ldap_result will wait for a response with msgid. If all is 0 the 71*7c478bd9Sstevel@tonic-gate * first message with id msgid will be accepted, otherwise, ldap_result 72*7c478bd9Sstevel@tonic-gate * will wait for all responses with id msgid and then return a pointer to 73*7c478bd9Sstevel@tonic-gate * the entire list of messages. This is only useful for search responses, 74*7c478bd9Sstevel@tonic-gate * which can be of two message types (zero or more entries, followed by an 75*7c478bd9Sstevel@tonic-gate * ldap result). The type of the first message received is returned. 76*7c478bd9Sstevel@tonic-gate * When waiting, any messages that have been abandoned are discarded. 77*7c478bd9Sstevel@tonic-gate * 78*7c478bd9Sstevel@tonic-gate * Example: 79*7c478bd9Sstevel@tonic-gate * ldap_result( s, msgid, all, timeout, result ) 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate int 82*7c478bd9Sstevel@tonic-gate LDAP_CALL 83*7c478bd9Sstevel@tonic-gate ldap_result( 84*7c478bd9Sstevel@tonic-gate LDAP *ld, 85*7c478bd9Sstevel@tonic-gate int msgid, 86*7c478bd9Sstevel@tonic-gate int all, 87*7c478bd9Sstevel@tonic-gate struct timeval *timeout, 88*7c478bd9Sstevel@tonic-gate LDAPMessage **result 89*7c478bd9Sstevel@tonic-gate ) 90*7c478bd9Sstevel@tonic-gate { 91*7c478bd9Sstevel@tonic-gate int rc; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 ); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 96*7c478bd9Sstevel@tonic-gate return( -1 ); /* punt */ 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_RESULT_LOCK ); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate rc = nsldapi_result_nolock(ld, msgid, all, 1, timeout, result); 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESULT_LOCK ); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate return( rc ); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate int 110*7c478bd9Sstevel@tonic-gate nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted, 111*7c478bd9Sstevel@tonic-gate struct timeval *timeout, LDAPMessage **result ) 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate int rc; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 116*7c478bd9Sstevel@tonic-gate "nsldapi_result_nolock (msgid=%d, all=%d)\n", msgid, all, 0 ); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * First, look through the list of responses we have received on 120*7c478bd9Sstevel@tonic-gate * this association and see if the response we're interested in 121*7c478bd9Sstevel@tonic-gate * is there. If it is, return it. If not, call wait4msg() to 122*7c478bd9Sstevel@tonic-gate * wait until it arrives or timeout occurs. 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate if ( result == NULL ) { 126*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); 127*7c478bd9Sstevel@tonic-gate return( -1 ); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate if ( check_response_queue( ld, msgid, all, 1, result ) != 0 ) { 131*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); 132*7c478bd9Sstevel@tonic-gate rc = (*result)->lm_msgtype; 133*7c478bd9Sstevel@tonic-gate } else { 134*7c478bd9Sstevel@tonic-gate rc = wait4msg( ld, msgid, all, unlock_permitted, timeout, 135*7c478bd9Sstevel@tonic-gate result ); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * XXXmcs should use cache function pointers to hook in memcache 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate if ( ld->ld_memcache != NULL && NSLDAPI_SEARCH_RELATED_RESULT( rc ) && 142*7c478bd9Sstevel@tonic-gate !((*result)->lm_fromcache )) { 143*7c478bd9Sstevel@tonic-gate ldap_memcache_append( ld, (*result)->lm_msgid, 144*7c478bd9Sstevel@tonic-gate (all || NSLDAPI_IS_SEARCH_RESULT( rc )), *result ); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate return( rc ); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * Look through the list of queued responses for a message that matches the 153*7c478bd9Sstevel@tonic-gate * criteria in the msgid and all parameters. msgid == LDAP_RES_ANY matches 154*7c478bd9Sstevel@tonic-gate * all ids. 155*7c478bd9Sstevel@tonic-gate * 156*7c478bd9Sstevel@tonic-gate * If an appropriate message is found, a non-zero value is returned and the 157*7c478bd9Sstevel@tonic-gate * message is dequeued and assigned to *result. 158*7c478bd9Sstevel@tonic-gate * 159*7c478bd9Sstevel@tonic-gate * If not, *result is set to NULL and this function returns 0. 160*7c478bd9Sstevel@tonic-gate */ 161*7c478bd9Sstevel@tonic-gate static int 162*7c478bd9Sstevel@tonic-gate check_response_queue( LDAP *ld, int msgid, int all, int do_abandon_check, 163*7c478bd9Sstevel@tonic-gate LDAPMessage **result ) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate LDAPMessage *lm, *lastlm, *nextlm; 166*7c478bd9Sstevel@tonic-gate LDAPRequest *lr; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 169*7c478bd9Sstevel@tonic-gate "=> check_response_queue (msgid=%d, all=%d)\n", msgid, all, 0 ); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate *result = NULL; 172*7c478bd9Sstevel@tonic-gate lastlm = NULL; 173*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); 174*7c478bd9Sstevel@tonic-gate for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { 175*7c478bd9Sstevel@tonic-gate nextlm = lm->lm_next; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if ( do_abandon_check && ldap_abandoned( ld, lm->lm_msgid ) ) { 178*7c478bd9Sstevel@tonic-gate ldap_mark_abandoned( ld, lm->lm_msgid ); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) { 181*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 182*7c478bd9Sstevel@tonic-gate } else { 183*7c478bd9Sstevel@tonic-gate lastlm->lm_next = nextlm; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate ldap_msgfree( lm ); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate continue; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { 192*7c478bd9Sstevel@tonic-gate LDAPMessage *tmp; 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate if ( all == 0 195*7c478bd9Sstevel@tonic-gate || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT 196*7c478bd9Sstevel@tonic-gate && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE 197*7c478bd9Sstevel@tonic-gate && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) 198*7c478bd9Sstevel@tonic-gate break; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { 201*7c478bd9Sstevel@tonic-gate if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate if ( tmp == NULL ) { 206*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 207*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 208*7c478bd9Sstevel@tonic-gate "<= check_response_queue NOT FOUND\n", 209*7c478bd9Sstevel@tonic-gate 0, 0, 0 ); 210*7c478bd9Sstevel@tonic-gate return( 0 ); /* no message to return */ 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate break; 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate lastlm = lm; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * if we did not find a message OR if the one we found is a result for 220*7c478bd9Sstevel@tonic-gate * a request that is still pending, return failure. 221*7c478bd9Sstevel@tonic-gate */ 222*7c478bd9Sstevel@tonic-gate if ( lm == NULL 223*7c478bd9Sstevel@tonic-gate || (( lr = nsldapi_find_request_by_msgid( ld, lm->lm_msgid )) 224*7c478bd9Sstevel@tonic-gate != NULL && lr->lr_outrefcnt > 0 )) { 225*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 226*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 227*7c478bd9Sstevel@tonic-gate "<= check_response_queue NOT FOUND\n", 228*7c478bd9Sstevel@tonic-gate 0, 0, 0 ); 229*7c478bd9Sstevel@tonic-gate return( 0 ); /* no message to return */ 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if ( all == 0 ) { 233*7c478bd9Sstevel@tonic-gate if ( lm->lm_chain == NULL ) { 234*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) { 235*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 236*7c478bd9Sstevel@tonic-gate } else { 237*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_next; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } else { 240*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) { 241*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_chain; 242*7c478bd9Sstevel@tonic-gate ld->ld_responses->lm_next = lm->lm_next; 243*7c478bd9Sstevel@tonic-gate } else { 244*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_chain; 245*7c478bd9Sstevel@tonic-gate lastlm->lm_next->lm_next = lm->lm_next; 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate } else { 249*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) { 250*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 251*7c478bd9Sstevel@tonic-gate } else { 252*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_next; 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate if ( all == 0 ) { 257*7c478bd9Sstevel@tonic-gate lm->lm_chain = NULL; 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate lm->lm_next = NULL; 260*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate *result = lm; 263*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 264*7c478bd9Sstevel@tonic-gate "<= check_response_queue returning msgid %d type %d\n", 265*7c478bd9Sstevel@tonic-gate lm->lm_msgid, lm->lm_msgtype, 0 ); 266*7c478bd9Sstevel@tonic-gate return( 1 ); /* a message was found and returned in *result */ 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate static int 271*7c478bd9Sstevel@tonic-gate wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, 272*7c478bd9Sstevel@tonic-gate struct timeval *timeout, LDAPMessage **result ) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate int rc; 275*7c478bd9Sstevel@tonic-gate struct timeval tv, *tvp; 276*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 277*7c478bd9Sstevel@tonic-gate hrtime_t start_time = 0, tmp_time, tv_time; 278*7c478bd9Sstevel@tonic-gate #else 279*7c478bd9Sstevel@tonic-gate long start_time = 0, tmp_time; 280*7c478bd9Sstevel@tonic-gate #endif 281*7c478bd9Sstevel@tonic-gate LDAPConn *lc, *nextlc; 282*7c478bd9Sstevel@tonic-gate LDAPRequest *lr; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG 285*7c478bd9Sstevel@tonic-gate if ( timeout == NULL ) { 286*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n", 287*7c478bd9Sstevel@tonic-gate 0, 0, 0 ); 288*7c478bd9Sstevel@tonic-gate } else { 289*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n", 290*7c478bd9Sstevel@tonic-gate timeout->tv_sec, timeout->tv_usec, 0 ); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate #endif /* LDAP_DEBUG */ 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* check the cache */ 295*7c478bd9Sstevel@tonic-gate if ( ld->ld_cache_on && ld->ld_cache_result != NULL ) { 296*7c478bd9Sstevel@tonic-gate /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */ 297*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); 298*7c478bd9Sstevel@tonic-gate rc = (ld->ld_cache_result)( ld, msgid, all, timeout, result ); 299*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); 300*7c478bd9Sstevel@tonic-gate /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */ 301*7c478bd9Sstevel@tonic-gate if ( rc != 0 ) { 302*7c478bd9Sstevel@tonic-gate return( rc ); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate if ( ld->ld_cache_strategy == LDAP_CACHE_LOCALDB ) { 305*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL ); 306*7c478bd9Sstevel@tonic-gate return( 0 ); /* timeout */ 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * if we are looking for a specific msgid, check to see if it is 312*7c478bd9Sstevel@tonic-gate * associated with a dead connection and return an error if so. 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate if ( msgid != LDAP_RES_ANY && msgid != LDAP_RES_UNSOLICITED ) { 315*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); 316*7c478bd9Sstevel@tonic-gate if (( lr = nsldapi_find_request_by_msgid( ld, msgid )) 317*7c478bd9Sstevel@tonic-gate == NULL ) { 318*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 319*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, 320*7c478bd9Sstevel@tonic-gate nsldapi_strdup( dgettext(TEXT_DOMAIN, 321*7c478bd9Sstevel@tonic-gate "unknown message id") )); 322*7c478bd9Sstevel@tonic-gate return( -1 ); /* could not find request for msgid */ 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate if ( lr->lr_conn != NULL && 325*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_status == LDAP_CONNST_DEAD ) { 326*7c478bd9Sstevel@tonic-gate nsldapi_free_request( ld, lr, 1 ); 327*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 328*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); 329*7c478bd9Sstevel@tonic-gate return( -1 ); /* connection dead */ 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if ( timeout == NULL ) { 335*7c478bd9Sstevel@tonic-gate tvp = NULL; 336*7c478bd9Sstevel@tonic-gate } else { 337*7c478bd9Sstevel@tonic-gate tv = *timeout; 338*7c478bd9Sstevel@tonic-gate tvp = &tv; 339*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 340*7c478bd9Sstevel@tonic-gate start_time = gethrtime(); 341*7c478bd9Sstevel@tonic-gate tv_time = ((hrtime_t)tv.tv_sec * NANOSEC + 342*7c478bd9Sstevel@tonic-gate (hrtime_t)tv.tv_usec * (NANOSEC / MICROSEC)); 343*7c478bd9Sstevel@tonic-gate #else 344*7c478bd9Sstevel@tonic-gate start_time = (long)time( NULL ); 345*7c478bd9Sstevel@tonic-gate #endif 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate rc = -2; 349*7c478bd9Sstevel@tonic-gate while ( rc == -2 ) { 350*7c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG 351*7c478bd9Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_TRACE ) { 352*7c478bd9Sstevel@tonic-gate nsldapi_dump_connection( ld, ld->ld_conns, 1 ); 353*7c478bd9Sstevel@tonic-gate nsldapi_dump_requests_and_responses( ld ); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate #endif /* LDAP_DEBUG */ 356*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); 357*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); 358*7c478bd9Sstevel@tonic-gate for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { 359*7c478bd9Sstevel@tonic-gate if ( lc->lconn_sb->sb_ber.ber_ptr < 360*7c478bd9Sstevel@tonic-gate lc->lconn_sb->sb_ber.ber_end ) { 361*7c478bd9Sstevel@tonic-gate rc = read1msg( ld, msgid, all, lc->lconn_sb, 362*7c478bd9Sstevel@tonic-gate lc, result ); 363*7c478bd9Sstevel@tonic-gate break; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 367*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if ( lc == NULL ) { 370*7c478bd9Sstevel@tonic-gate rc = nsldapi_iostatus_poll( ld, tvp ); 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate #if defined( LDAP_DEBUG ) && !defined( macintosh ) && !defined( DOS ) 373*7c478bd9Sstevel@tonic-gate if ( rc == -1 ) { 374*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 375*7c478bd9Sstevel@tonic-gate "nsldapi_iostatus_poll returned -1: errno %d\n", 376*7c478bd9Sstevel@tonic-gate LDAP_GET_ERRNO( ld ), 0, 0 ); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate #endif 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate #if !defined( macintosh ) && !defined( DOS ) 381*7c478bd9Sstevel@tonic-gate if ( rc == 0 || ( rc == -1 && (( ld->ld_options & 382*7c478bd9Sstevel@tonic-gate LDAP_BITOPT_RESTART ) == 0 || 383*7c478bd9Sstevel@tonic-gate LDAP_GET_ERRNO( ld ) != EINTR ))) { 384*7c478bd9Sstevel@tonic-gate #else 385*7c478bd9Sstevel@tonic-gate if ( rc == -1 || rc == 0 ) { 386*7c478bd9Sstevel@tonic-gate #endif 387*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, (rc == -1 ? 388*7c478bd9Sstevel@tonic-gate LDAP_SERVER_DOWN : LDAP_TIMEOUT), NULL, 389*7c478bd9Sstevel@tonic-gate NULL ); 390*7c478bd9Sstevel@tonic-gate if ( rc == -1 ) { 391*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); 392*7c478bd9Sstevel@tonic-gate nsldapi_connection_lost_nolock( ld, 393*7c478bd9Sstevel@tonic-gate NULL ); 394*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate return( rc ); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate if ( rc == -1 ) { 400*7c478bd9Sstevel@tonic-gate rc = -2; /* select interrupted: loop */ 401*7c478bd9Sstevel@tonic-gate } else { 402*7c478bd9Sstevel@tonic-gate rc = -2; 403*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); 404*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); 405*7c478bd9Sstevel@tonic-gate for ( lc = ld->ld_conns; rc == -2 && lc != NULL; 406*7c478bd9Sstevel@tonic-gate lc = nextlc ) { 407*7c478bd9Sstevel@tonic-gate nextlc = lc->lconn_next; 408*7c478bd9Sstevel@tonic-gate if ( lc->lconn_status == 409*7c478bd9Sstevel@tonic-gate LDAP_CONNST_CONNECTED && 410*7c478bd9Sstevel@tonic-gate nsldapi_iostatus_is_read_ready( ld, 411*7c478bd9Sstevel@tonic-gate lc->lconn_sb )) { 412*7c478bd9Sstevel@tonic-gate rc = read1msg( ld, msgid, all, 413*7c478bd9Sstevel@tonic-gate lc->lconn_sb, lc, result ); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate else if (ld->ld_options & LDAP_BITOPT_ASYNC) { 416*7c478bd9Sstevel@tonic-gate if ( lr 417*7c478bd9Sstevel@tonic-gate && lc->lconn_status == LDAP_CONNST_CONNECTING 418*7c478bd9Sstevel@tonic-gate && nsldapi_iostatus_is_write_ready( ld, 419*7c478bd9Sstevel@tonic-gate lc->lconn_sb ) ) { 420*7c478bd9Sstevel@tonic-gate rc = nsldapi_ber_flush( ld, lc->lconn_sb, lr->lr_ber, 0, 1 ); 421*7c478bd9Sstevel@tonic-gate if ( rc == 0 ) { 422*7c478bd9Sstevel@tonic-gate rc = LDAP_RES_BIND; 423*7c478bd9Sstevel@tonic-gate lc->lconn_status = LDAP_CONNST_CONNECTED; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate lr->lr_ber->ber_end = lr->lr_ber->ber_ptr; 426*7c478bd9Sstevel@tonic-gate lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf; 427*7c478bd9Sstevel@tonic-gate nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate else if ( rc == -1 ) { 430*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); 431*7c478bd9Sstevel@tonic-gate nsldapi_free_request( ld, lr, 0 ); 432*7c478bd9Sstevel@tonic-gate nsldapi_free_connection( ld, lc, NULL, NULL, 433*7c478bd9Sstevel@tonic-gate 0, 0 ); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); 440*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * It is possible that recursion occurred while chasing 446*7c478bd9Sstevel@tonic-gate * referrals and as a result the message we are looking 447*7c478bd9Sstevel@tonic-gate * for may have been placed on the response queue. Look 448*7c478bd9Sstevel@tonic-gate * for it there before continuing so we don't end up 449*7c478bd9Sstevel@tonic-gate * waiting on the network for a message that we already 450*7c478bd9Sstevel@tonic-gate * received! 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate if ( rc == -2 && 453*7c478bd9Sstevel@tonic-gate check_response_queue( ld, msgid, all, 0, result ) != 0 ) { 454*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); 455*7c478bd9Sstevel@tonic-gate rc = (*result)->lm_msgtype; 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * honor the timeout if specified 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate if ( rc == -2 && tvp != NULL ) { 462*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 463*7c478bd9Sstevel@tonic-gate tmp_time = gethrtime(); 464*7c478bd9Sstevel@tonic-gate if ((tv_time -= (tmp_time - start_time)) <= 0) { 465*7c478bd9Sstevel@tonic-gate #else 466*7c478bd9Sstevel@tonic-gate tmp_time = (long)time( NULL ); 467*7c478bd9Sstevel@tonic-gate if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) { 468*7c478bd9Sstevel@tonic-gate #endif 469*7c478bd9Sstevel@tonic-gate rc = 0; /* timed out */ 470*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, 471*7c478bd9Sstevel@tonic-gate NULL ); 472*7c478bd9Sstevel@tonic-gate break; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 476*7c478bd9Sstevel@tonic-gate tv.tv_sec = tv_time / NANOSEC; 477*7c478bd9Sstevel@tonic-gate tv.tv_usec = (tv_time % NANOSEC) / (NANOSEC / MICROSEC); 478*7c478bd9Sstevel@tonic-gate #endif 479*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg: %ld secs to go\n", 480*7c478bd9Sstevel@tonic-gate tv.tv_sec, 0, 0 ); 481*7c478bd9Sstevel@tonic-gate start_time = tmp_time; 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate return( rc ); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * read1msg() should be called with LDAP_CONN_LOCK and LDAP_REQ_LOCK locked. 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate static int 493*7c478bd9Sstevel@tonic-gate read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc, 494*7c478bd9Sstevel@tonic-gate LDAPMessage **result ) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate BerElement *ber; 497*7c478bd9Sstevel@tonic-gate LDAPMessage *new, *l, *prev, *chainprev, *tmp; 498*7c478bd9Sstevel@tonic-gate ber_int_t id; 499*7c478bd9Sstevel@tonic-gate ber_tag_t tag; 500*7c478bd9Sstevel@tonic-gate ber_len_t len; 501*7c478bd9Sstevel@tonic-gate int terrno, lderr, foundit = 0; 502*7c478bd9Sstevel@tonic-gate LDAPRequest *lr; 503*7c478bd9Sstevel@tonic-gate int rc, has_parent, message_can_be_returned; 504*7c478bd9Sstevel@tonic-gate int manufactured_result = 0; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 ); 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate message_can_be_returned = 1; /* the usual case... */ 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate /* 511*7c478bd9Sstevel@tonic-gate * if we are not already in the midst of reading a message, allocate 512*7c478bd9Sstevel@tonic-gate * a ber that is associated with this connection 513*7c478bd9Sstevel@tonic-gate */ 514*7c478bd9Sstevel@tonic-gate if ( lc->lconn_ber == NULLBER && nsldapi_alloc_ber_with_options( ld, 515*7c478bd9Sstevel@tonic-gate &lc->lconn_ber ) != LDAP_SUCCESS ) { 516*7c478bd9Sstevel@tonic-gate return( -1 ); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * ber_get_next() doesn't set errno on EOF, so we pre-set it to 521*7c478bd9Sstevel@tonic-gate * zero to avoid getting tricked by leftover "EAGAIN" errors 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO( ld, 0 ); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* get the next message */ 526*7c478bd9Sstevel@tonic-gate if ( (tag = ber_get_next( sb, &len, lc->lconn_ber )) 527*7c478bd9Sstevel@tonic-gate != LDAP_TAG_MESSAGE ) { 528*7c478bd9Sstevel@tonic-gate terrno = LDAP_GET_ERRNO( ld ); 529*7c478bd9Sstevel@tonic-gate if ( terrno == EWOULDBLOCK || terrno == EAGAIN ) { 530*7c478bd9Sstevel@tonic-gate return( -2 ); /* try again */ 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : 533*7c478bd9Sstevel@tonic-gate LDAP_LOCAL_ERROR), NULL, NULL ); 534*7c478bd9Sstevel@tonic-gate if ( tag == LBER_DEFAULT ) { 535*7c478bd9Sstevel@tonic-gate nsldapi_connection_lost_nolock( ld, sb ); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate return( -1 ); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * Since we have received a complete message now, we pull this ber 542*7c478bd9Sstevel@tonic-gate * out of the connection structure and never read into it again. 543*7c478bd9Sstevel@tonic-gate */ 544*7c478bd9Sstevel@tonic-gate ber = lc->lconn_ber; 545*7c478bd9Sstevel@tonic-gate lc->lconn_ber = NULLBER; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* message id */ 548*7c478bd9Sstevel@tonic-gate if ( ber_get_int( ber, &id ) == LBER_ERROR ) { 549*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); 550*7c478bd9Sstevel@tonic-gate return( -1 ); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* if it's been abandoned, toss it */ 554*7c478bd9Sstevel@tonic-gate if ( ldap_abandoned( ld, (int)id ) ) { 555*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 ); 556*7c478bd9Sstevel@tonic-gate return( -2 ); /* continue looking */ 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if ( id == LDAP_RES_UNSOLICITED ) { 560*7c478bd9Sstevel@tonic-gate lr = NULL; 561*7c478bd9Sstevel@tonic-gate } else if (( lr = nsldapi_find_request_by_msgid( ld, id )) == NULL ) { 562*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY, 563*7c478bd9Sstevel@tonic-gate "no request for response with msgid %ld (tossing)\n", 564*7c478bd9Sstevel@tonic-gate id, 0, 0 ); 565*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 ); 566*7c478bd9Sstevel@tonic-gate return( -2 ); /* continue looking */ 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate /* the message type */ 570*7c478bd9Sstevel@tonic-gate if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { 571*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); 572*7c478bd9Sstevel@tonic-gate return( -1 ); 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "got %s msgid %ld, original id %d\n", 575*7c478bd9Sstevel@tonic-gate ( tag == LDAP_RES_SEARCH_ENTRY ) ? "ENTRY" : 576*7c478bd9Sstevel@tonic-gate ( tag == LDAP_RES_SEARCH_REFERENCE ) ? "REFERENCE" : "RESULT", id, 577*7c478bd9Sstevel@tonic-gate ( lr == NULL ) ? id : lr->lr_origid ); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if ( lr != NULL ) { 580*7c478bd9Sstevel@tonic-gate id = lr->lr_origid; 581*7c478bd9Sstevel@tonic-gate lr->lr_res_msgtype = tag; 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate rc = -2; /* default is to keep looking (no response found) */ 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate if ( id != LDAP_RES_UNSOLICITED && ( tag == LDAP_RES_SEARCH_REFERENCE || 586*7c478bd9Sstevel@tonic-gate tag != LDAP_RES_SEARCH_ENTRY )) { 587*7c478bd9Sstevel@tonic-gate int refchasing, reftotal, simple_request = 0; 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate check_for_refs( ld, lr, ber, lc->lconn_version, &reftotal, 590*7c478bd9Sstevel@tonic-gate &refchasing ); 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate if ( refchasing > 0 || lr->lr_outrefcnt > 0 ) { 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * we're chasing one or more new refs... 595*7c478bd9Sstevel@tonic-gate */ 596*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 ); 597*7c478bd9Sstevel@tonic-gate ber = NULLBER; 598*7c478bd9Sstevel@tonic-gate lr->lr_status = LDAP_REQST_CHASINGREFS; 599*7c478bd9Sstevel@tonic-gate message_can_be_returned = 0; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate } else if ( tag != LDAP_RES_SEARCH_REFERENCE ) { 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * this request is complete... 604*7c478bd9Sstevel@tonic-gate */ 605*7c478bd9Sstevel@tonic-gate has_parent = ( lr->lr_parent != NULL ); 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if ( lr->lr_outrefcnt <= 0 && !has_parent ) { 608*7c478bd9Sstevel@tonic-gate /* request without any refs */ 609*7c478bd9Sstevel@tonic-gate simple_request = ( reftotal == 0 ); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * If this is not a child request and it is a bind 614*7c478bd9Sstevel@tonic-gate * request, reset the connection's bind DN and 615*7c478bd9Sstevel@tonic-gate * status based on the result of the operation. 616*7c478bd9Sstevel@tonic-gate */ 617*7c478bd9Sstevel@tonic-gate if ( !has_parent && 618*7c478bd9Sstevel@tonic-gate LDAP_RES_BIND == lr->lr_res_msgtype && 619*7c478bd9Sstevel@tonic-gate lr->lr_conn != NULL ) { 620*7c478bd9Sstevel@tonic-gate if ( lr->lr_conn->lconn_binddn != NULL ) { 621*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( 622*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_binddn ); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate if ( LDAP_SUCCESS == nsldapi_parse_result( ld, 625*7c478bd9Sstevel@tonic-gate lr->lr_res_msgtype, ber, &lderr, NULL, 626*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL ) 627*7c478bd9Sstevel@tonic-gate && LDAP_SUCCESS == lderr ) { 628*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_bound = 1; 629*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_binddn = 630*7c478bd9Sstevel@tonic-gate lr->lr_binddn; 631*7c478bd9Sstevel@tonic-gate lr->lr_binddn = NULL; 632*7c478bd9Sstevel@tonic-gate } else { 633*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_bound = 0; 634*7c478bd9Sstevel@tonic-gate lr->lr_conn->lconn_binddn = NULL; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate /* 639*7c478bd9Sstevel@tonic-gate * if this response is to a child request, we toss 640*7c478bd9Sstevel@tonic-gate * the message contents and just merge error info. 641*7c478bd9Sstevel@tonic-gate * into the parent. 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate if ( has_parent ) { 644*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 ); 645*7c478bd9Sstevel@tonic-gate ber = NULLBER; 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate while ( lr->lr_parent != NULL ) { 648*7c478bd9Sstevel@tonic-gate merge_error_info( ld, lr->lr_parent, lr ); 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate lr = lr->lr_parent; 651*7c478bd9Sstevel@tonic-gate if ( --lr->lr_outrefcnt > 0 ) { 652*7c478bd9Sstevel@tonic-gate break; /* not completely done yet */ 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * we recognize a request as complete when: 658*7c478bd9Sstevel@tonic-gate * 1) it has no outstanding referrals 659*7c478bd9Sstevel@tonic-gate * 2) it is not a child request 660*7c478bd9Sstevel@tonic-gate * 3) we have received a result for the request (i.e., 661*7c478bd9Sstevel@tonic-gate * something other than an entry or a reference). 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL && 664*7c478bd9Sstevel@tonic-gate lr->lr_res_msgtype != LDAP_RES_SEARCH_ENTRY && 665*7c478bd9Sstevel@tonic-gate lr->lr_res_msgtype != LDAP_RES_SEARCH_REFERENCE ) { 666*7c478bd9Sstevel@tonic-gate id = lr->lr_msgid; 667*7c478bd9Sstevel@tonic-gate tag = lr->lr_res_msgtype; 668*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 669*7c478bd9Sstevel@tonic-gate "request %ld done\n", id, 0, 0 ); 670*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 671*7c478bd9Sstevel@tonic-gate "res_errno: %d, res_error: <%s>, res_matched: <%s>\n", 672*7c478bd9Sstevel@tonic-gate lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", 673*7c478bd9Sstevel@tonic-gate lr->lr_res_matched ? lr->lr_res_matched : "" ); 674*7c478bd9Sstevel@tonic-gate if ( !simple_request ) { 675*7c478bd9Sstevel@tonic-gate if ( ber != NULLBER ) { 676*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 ); 677*7c478bd9Sstevel@tonic-gate ber = NULLBER; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate if ( build_result_ber( ld, &ber, lr ) 680*7c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) { 681*7c478bd9Sstevel@tonic-gate rc = -1; /* fatal error */ 682*7c478bd9Sstevel@tonic-gate } else { 683*7c478bd9Sstevel@tonic-gate manufactured_result = 1; 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate nsldapi_free_request( ld, lr, 1 ); 688*7c478bd9Sstevel@tonic-gate } else { 689*7c478bd9Sstevel@tonic-gate message_can_be_returned = 0; 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate if ( ber == NULLBER ) { 695*7c478bd9Sstevel@tonic-gate return( rc ); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate /* make a new ldap message */ 699*7c478bd9Sstevel@tonic-gate if ( (new = (LDAPMessage*)NSLDAPI_CALLOC( 1, sizeof(struct ldapmsg) )) 700*7c478bd9Sstevel@tonic-gate == NULL ) { 701*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); 702*7c478bd9Sstevel@tonic-gate return( -1 ); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate new->lm_msgid = (int)id; 705*7c478bd9Sstevel@tonic-gate new->lm_msgtype = tag; 706*7c478bd9Sstevel@tonic-gate new->lm_ber = ber; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * if this is a search entry or if this request is complete (i.e., 710*7c478bd9Sstevel@tonic-gate * there are no outstanding referrals) then add to cache and check 711*7c478bd9Sstevel@tonic-gate * to see if we should return this to the caller right away or not. 712*7c478bd9Sstevel@tonic-gate */ 713*7c478bd9Sstevel@tonic-gate if ( message_can_be_returned ) { 714*7c478bd9Sstevel@tonic-gate if ( ld->ld_cache_on ) { 715*7c478bd9Sstevel@tonic-gate nsldapi_add_result_to_cache( ld, new ); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if ( msgid == LDAP_RES_ANY || id == msgid ) { 719*7c478bd9Sstevel@tonic-gate if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { 720*7c478bd9Sstevel@tonic-gate /* 721*7c478bd9Sstevel@tonic-gate * return the first response we have for this 722*7c478bd9Sstevel@tonic-gate * search request later (possibly an entire 723*7c478bd9Sstevel@tonic-gate * chain of messages). 724*7c478bd9Sstevel@tonic-gate */ 725*7c478bd9Sstevel@tonic-gate foundit = 1; 726*7c478bd9Sstevel@tonic-gate } else if ( all == 0 727*7c478bd9Sstevel@tonic-gate || (new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE 728*7c478bd9Sstevel@tonic-gate && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) { 729*7c478bd9Sstevel@tonic-gate *result = new; 730*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, 731*7c478bd9Sstevel@tonic-gate NULL ); 732*7c478bd9Sstevel@tonic-gate return( tag ); 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate /* 738*7c478bd9Sstevel@tonic-gate * if not, we must add it to the list of responses. if 739*7c478bd9Sstevel@tonic-gate * the msgid is already there, it must be part of an existing 740*7c478bd9Sstevel@tonic-gate * search response. 741*7c478bd9Sstevel@tonic-gate */ 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate prev = NULL; 744*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); 745*7c478bd9Sstevel@tonic-gate for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) { 746*7c478bd9Sstevel@tonic-gate if ( l->lm_msgid == new->lm_msgid ) 747*7c478bd9Sstevel@tonic-gate break; 748*7c478bd9Sstevel@tonic-gate prev = l; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* not part of an existing search response */ 752*7c478bd9Sstevel@tonic-gate if ( l == NULL ) { 753*7c478bd9Sstevel@tonic-gate if ( foundit ) { 754*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 755*7c478bd9Sstevel@tonic-gate *result = new; 756*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); 757*7c478bd9Sstevel@tonic-gate return( tag ); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate new->lm_next = ld->ld_responses; 761*7c478bd9Sstevel@tonic-gate ld->ld_responses = new; 762*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 763*7c478bd9Sstevel@tonic-gate "adding new response id %d type %d (looking for id %d)\n", 764*7c478bd9Sstevel@tonic-gate new->lm_msgid, new->lm_msgtype, msgid ); 765*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 766*7c478bd9Sstevel@tonic-gate if( message_can_be_returned ) 767*7c478bd9Sstevel@tonic-gate POST( ld, new->lm_msgid, new ); 768*7c478bd9Sstevel@tonic-gate return( -2 ); /* continue looking */ 769*7c478bd9Sstevel@tonic-gate } 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 772*7c478bd9Sstevel@tonic-gate "adding response id %d type %d (looking for id %d)\n", 773*7c478bd9Sstevel@tonic-gate new->lm_msgid, new->lm_msgtype, msgid ); 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate /* 776*7c478bd9Sstevel@tonic-gate * part of a search response - add to end of list of entries 777*7c478bd9Sstevel@tonic-gate * 778*7c478bd9Sstevel@tonic-gate * the first step is to find the end of the list of entries and 779*7c478bd9Sstevel@tonic-gate * references. after the following loop is executed, tmp points to 780*7c478bd9Sstevel@tonic-gate * the last entry or reference in the chain. If there are none, 781*7c478bd9Sstevel@tonic-gate * tmp points to the search result. 782*7c478bd9Sstevel@tonic-gate */ 783*7c478bd9Sstevel@tonic-gate chainprev = NULL; 784*7c478bd9Sstevel@tonic-gate for ( tmp = l; tmp->lm_chain != NULL && 785*7c478bd9Sstevel@tonic-gate ( tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY 786*7c478bd9Sstevel@tonic-gate || tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ); 787*7c478bd9Sstevel@tonic-gate tmp = tmp->lm_chain ) { 788*7c478bd9Sstevel@tonic-gate chainprev = tmp; 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * If this is a manufactured result message and a result is already 793*7c478bd9Sstevel@tonic-gate * queued we throw away the one that is queued and replace it with 794*7c478bd9Sstevel@tonic-gate * our new result. This is necessary so we don't end up returning 795*7c478bd9Sstevel@tonic-gate * more than one result. 796*7c478bd9Sstevel@tonic-gate */ 797*7c478bd9Sstevel@tonic-gate if ( manufactured_result && 798*7c478bd9Sstevel@tonic-gate tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * the result is the only thing in the chain... replace it. 801*7c478bd9Sstevel@tonic-gate */ 802*7c478bd9Sstevel@tonic-gate new->lm_chain = tmp->lm_chain; 803*7c478bd9Sstevel@tonic-gate new->lm_next = tmp->lm_next; 804*7c478bd9Sstevel@tonic-gate if ( chainprev == NULL ) { 805*7c478bd9Sstevel@tonic-gate if ( prev == NULL ) { 806*7c478bd9Sstevel@tonic-gate ld->ld_responses = new; 807*7c478bd9Sstevel@tonic-gate } else { 808*7c478bd9Sstevel@tonic-gate prev->lm_next = new; 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate } else { 811*7c478bd9Sstevel@tonic-gate chainprev->lm_chain = new; 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate if ( l == tmp ) { 814*7c478bd9Sstevel@tonic-gate l = new; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate ldap_msgfree( tmp ); 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate } else if ( manufactured_result && tmp->lm_chain != NULL 819*7c478bd9Sstevel@tonic-gate && tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { 820*7c478bd9Sstevel@tonic-gate /* 821*7c478bd9Sstevel@tonic-gate * entries or references are also present, so the result 822*7c478bd9Sstevel@tonic-gate * is the next entry after tmp. replace it. 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate new->lm_chain = tmp->lm_chain->lm_chain; 825*7c478bd9Sstevel@tonic-gate new->lm_next = tmp->lm_chain->lm_next; 826*7c478bd9Sstevel@tonic-gate ldap_msgfree( tmp->lm_chain ); 827*7c478bd9Sstevel@tonic-gate tmp->lm_chain = new; 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate } else if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * the result is the only thing in the chain... add before it. 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate new->lm_chain = tmp; 834*7c478bd9Sstevel@tonic-gate if ( chainprev == NULL ) { 835*7c478bd9Sstevel@tonic-gate if ( prev == NULL ) { 836*7c478bd9Sstevel@tonic-gate ld->ld_responses = new; 837*7c478bd9Sstevel@tonic-gate } else { 838*7c478bd9Sstevel@tonic-gate prev->lm_next = new; 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate } else { 841*7c478bd9Sstevel@tonic-gate chainprev->lm_chain = new; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate if ( l == tmp ) { 844*7c478bd9Sstevel@tonic-gate l = new; 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate } else { 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * entries and/or references are present... add to the end 850*7c478bd9Sstevel@tonic-gate * of the entry/reference part of the chain. 851*7c478bd9Sstevel@tonic-gate */ 852*7c478bd9Sstevel@tonic-gate new->lm_chain = tmp->lm_chain; 853*7c478bd9Sstevel@tonic-gate tmp->lm_chain = new; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* 857*7c478bd9Sstevel@tonic-gate * return the first response or the whole chain if that's what 858*7c478bd9Sstevel@tonic-gate * we were looking for.... 859*7c478bd9Sstevel@tonic-gate */ 860*7c478bd9Sstevel@tonic-gate if ( foundit ) { 861*7c478bd9Sstevel@tonic-gate if ( all == 0 && l->lm_chain != NULL ) { 862*7c478bd9Sstevel@tonic-gate /* 863*7c478bd9Sstevel@tonic-gate * only return the first response in the chain 864*7c478bd9Sstevel@tonic-gate */ 865*7c478bd9Sstevel@tonic-gate if ( prev == NULL ) { 866*7c478bd9Sstevel@tonic-gate ld->ld_responses = l->lm_chain; 867*7c478bd9Sstevel@tonic-gate } else { 868*7c478bd9Sstevel@tonic-gate prev->lm_next = l->lm_chain; 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate l->lm_chain = NULL; 871*7c478bd9Sstevel@tonic-gate tag = l->lm_msgtype; 872*7c478bd9Sstevel@tonic-gate } else { 873*7c478bd9Sstevel@tonic-gate /* 874*7c478bd9Sstevel@tonic-gate * return all of the responses (may be a chain) 875*7c478bd9Sstevel@tonic-gate */ 876*7c478bd9Sstevel@tonic-gate if ( prev == NULL ) { 877*7c478bd9Sstevel@tonic-gate ld->ld_responses = l->lm_next; 878*7c478bd9Sstevel@tonic-gate } else { 879*7c478bd9Sstevel@tonic-gate prev->lm_next = l->lm_next; 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate *result = l; 883*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 884*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); 885*7c478bd9Sstevel@tonic-gate return( tag ); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 888*7c478bd9Sstevel@tonic-gate return( -2 ); /* continue looking */ 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate /* 893*7c478bd9Sstevel@tonic-gate * check for LDAPv2+ (UMich extension) or LDAPv3 referrals or references 894*7c478bd9Sstevel@tonic-gate * errors are merged in "lr". 895*7c478bd9Sstevel@tonic-gate */ 896*7c478bd9Sstevel@tonic-gate static void 897*7c478bd9Sstevel@tonic-gate check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, 898*7c478bd9Sstevel@tonic-gate int ldapversion, int *totalcountp, int *chasingcountp ) 899*7c478bd9Sstevel@tonic-gate { 900*7c478bd9Sstevel@tonic-gate int err, origerr; 901*7c478bd9Sstevel@tonic-gate char *errstr, *matcheddn, **v3refs; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "check_for_refs\n", 0, 0, 0 ); 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate *chasingcountp = *totalcountp = 0; 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate if ( ldapversion < LDAP_VERSION2 || ( lr->lr_parent == NULL 908*7c478bd9Sstevel@tonic-gate && ( ld->ld_options & LDAP_BITOPT_REFERRALS ) == 0 )) { 909*7c478bd9Sstevel@tonic-gate /* referrals are not supported or are disabled */ 910*7c478bd9Sstevel@tonic-gate return; 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate if ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ) { 914*7c478bd9Sstevel@tonic-gate err = nsldapi_parse_reference( ld, ber, &v3refs, NULL ); 915*7c478bd9Sstevel@tonic-gate origerr = LDAP_REFERRAL; /* a small lie... */ 916*7c478bd9Sstevel@tonic-gate matcheddn = errstr = NULL; 917*7c478bd9Sstevel@tonic-gate } else { 918*7c478bd9Sstevel@tonic-gate err = nsldapi_parse_result( ld, lr->lr_res_msgtype, ber, 919*7c478bd9Sstevel@tonic-gate &origerr, &matcheddn, &errstr, &v3refs, NULL ); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if ( err != LDAP_SUCCESS ) { 923*7c478bd9Sstevel@tonic-gate /* parse failed */ 924*7c478bd9Sstevel@tonic-gate return; 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate if ( origerr == LDAP_REFERRAL ) { /* ldapv3 */ 928*7c478bd9Sstevel@tonic-gate if ( v3refs != NULL ) { 929*7c478bd9Sstevel@tonic-gate err = nsldapi_chase_v3_refs( ld, lr, v3refs, 930*7c478bd9Sstevel@tonic-gate ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ), 931*7c478bd9Sstevel@tonic-gate totalcountp, chasingcountp ); 932*7c478bd9Sstevel@tonic-gate ldap_value_free( v3refs ); 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate } else if ( ldapversion == LDAP_VERSION2 935*7c478bd9Sstevel@tonic-gate && origerr != LDAP_SUCCESS ) { 936*7c478bd9Sstevel@tonic-gate /* referrals may be present in the error string */ 937*7c478bd9Sstevel@tonic-gate err = nsldapi_chase_v2_referrals( ld, lr, &errstr, 938*7c478bd9Sstevel@tonic-gate totalcountp, chasingcountp ); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate /* set LDAP errno, message, and matched string appropriately */ 942*7c478bd9Sstevel@tonic-gate if ( lr->lr_res_error != NULL ) { 943*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( lr->lr_res_error ); 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate lr->lr_res_error = errstr; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if ( lr->lr_res_matched != NULL ) { 948*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( lr->lr_res_matched ); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate lr->lr_res_matched = matcheddn; 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate if ( err == LDAP_SUCCESS && ( *chasingcountp == *totalcountp )) { 953*7c478bd9Sstevel@tonic-gate if ( *totalcountp > 0 && ( origerr == LDAP_PARTIAL_RESULTS 954*7c478bd9Sstevel@tonic-gate || origerr == LDAP_REFERRAL )) { 955*7c478bd9Sstevel@tonic-gate /* substitute success for referral error codes */ 956*7c478bd9Sstevel@tonic-gate lr->lr_res_errno = LDAP_SUCCESS; 957*7c478bd9Sstevel@tonic-gate } else { 958*7c478bd9Sstevel@tonic-gate /* preserve existing non-referral error code */ 959*7c478bd9Sstevel@tonic-gate lr->lr_res_errno = origerr; 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate } else if ( err != LDAP_SUCCESS ) { 962*7c478bd9Sstevel@tonic-gate /* error occurred while trying to chase referrals */ 963*7c478bd9Sstevel@tonic-gate lr->lr_res_errno = err; 964*7c478bd9Sstevel@tonic-gate } else { 965*7c478bd9Sstevel@tonic-gate /* some referrals were not recognized */ 966*7c478bd9Sstevel@tonic-gate lr->lr_res_errno = ( ldapversion == LDAP_VERSION2 ) 967*7c478bd9Sstevel@tonic-gate ? LDAP_PARTIAL_RESULTS : LDAP_REFERRAL; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 971*7c478bd9Sstevel@tonic-gate "check_for_refs: new result: msgid %d, res_errno %d, ", 972*7c478bd9Sstevel@tonic-gate lr->lr_msgid, lr->lr_res_errno, 0 ); 973*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, " res_error <%s>, res_matched <%s>\n", 974*7c478bd9Sstevel@tonic-gate lr->lr_res_error ? lr->lr_res_error : "", 975*7c478bd9Sstevel@tonic-gate lr->lr_res_matched ? lr->lr_res_matched : "", 0 ); 976*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 977*7c478bd9Sstevel@tonic-gate "check_for_refs: %d new refs(s); chasing %d of them\n", 978*7c478bd9Sstevel@tonic-gate *totalcountp, *chasingcountp, 0 ); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* returns an LDAP error code and also sets it in LDAP * */ 983*7c478bd9Sstevel@tonic-gate static int 984*7c478bd9Sstevel@tonic-gate build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ) 985*7c478bd9Sstevel@tonic-gate { 986*7c478bd9Sstevel@tonic-gate ber_len_t len; 987*7c478bd9Sstevel@tonic-gate ber_int_t along; 988*7c478bd9Sstevel@tonic-gate BerElement *ber; 989*7c478bd9Sstevel@tonic-gate int err; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) 992*7c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) { 993*7c478bd9Sstevel@tonic-gate return( err ); 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate *berp = ber; 996*7c478bd9Sstevel@tonic-gate if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid, 997*7c478bd9Sstevel@tonic-gate (long)lr->lr_res_msgtype, lr->lr_res_errno, 998*7c478bd9Sstevel@tonic-gate lr->lr_res_matched ? lr->lr_res_matched : "", 999*7c478bd9Sstevel@tonic-gate lr->lr_res_error ? lr->lr_res_error : "" ) == -1 ) { 1000*7c478bd9Sstevel@tonic-gate return( LDAP_ENCODING_ERROR ); 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate ber_reset( ber, 1 ); 1004*7c478bd9Sstevel@tonic-gate if ( ber_skip_tag( ber, &len ) == LBER_ERROR || 1005*7c478bd9Sstevel@tonic-gate ber_get_int( ber, &along ) == LBER_ERROR || 1006*7c478bd9Sstevel@tonic-gate ber_peek_tag( ber, &len ) == LBER_ERROR ) { 1007*7c478bd9Sstevel@tonic-gate return( LDAP_DECODING_ERROR ); 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS ); 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate static void 1015*7c478bd9Sstevel@tonic-gate merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) 1016*7c478bd9Sstevel@tonic-gate { 1017*7c478bd9Sstevel@tonic-gate /* 1018*7c478bd9Sstevel@tonic-gate * Merge error information in "lr" with "parentr" error code and string. 1019*7c478bd9Sstevel@tonic-gate */ 1020*7c478bd9Sstevel@tonic-gate if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { 1021*7c478bd9Sstevel@tonic-gate parentr->lr_res_errno = lr->lr_res_errno; 1022*7c478bd9Sstevel@tonic-gate if ( lr->lr_res_error != NULL ) { 1023*7c478bd9Sstevel@tonic-gate (void)nsldapi_append_referral( ld, &parentr->lr_res_error, 1024*7c478bd9Sstevel@tonic-gate lr->lr_res_error ); 1025*7c478bd9Sstevel@tonic-gate } 1026*7c478bd9Sstevel@tonic-gate } else if ( lr->lr_res_errno != LDAP_SUCCESS && 1027*7c478bd9Sstevel@tonic-gate parentr->lr_res_errno == LDAP_SUCCESS ) { 1028*7c478bd9Sstevel@tonic-gate parentr->lr_res_errno = lr->lr_res_errno; 1029*7c478bd9Sstevel@tonic-gate if ( parentr->lr_res_error != NULL ) { 1030*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( parentr->lr_res_error ); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate parentr->lr_res_error = lr->lr_res_error; 1033*7c478bd9Sstevel@tonic-gate lr->lr_res_error = NULL; 1034*7c478bd9Sstevel@tonic-gate if ( NAME_ERROR( lr->lr_res_errno )) { 1035*7c478bd9Sstevel@tonic-gate if ( parentr->lr_res_matched != NULL ) { 1036*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( parentr->lr_res_matched ); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate parentr->lr_res_matched = lr->lr_res_matched; 1039*7c478bd9Sstevel@tonic-gate lr->lr_res_matched = NULL; 1040*7c478bd9Sstevel@tonic-gate } 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ", 1044*7c478bd9Sstevel@tonic-gate parentr->lr_msgid, 0, 0 ); 1045*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "result lderrno %d, error <%s>, matched <%s>\n", 1046*7c478bd9Sstevel@tonic-gate parentr->lr_res_errno, parentr->lr_res_error ? 1047*7c478bd9Sstevel@tonic-gate parentr->lr_res_error : "", parentr->lr_res_matched ? 1048*7c478bd9Sstevel@tonic-gate parentr->lr_res_matched : "" ); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate #if defined( CLDAP ) 1052*7c478bd9Sstevel@tonic-gate #if !defined( macintosh ) && !defined( DOS ) && !defined( _WINDOWS ) && !defined(XP_OS2) 1053*7c478bd9Sstevel@tonic-gate /* XXXmcs: was revised to support extended I/O callbacks but never compiled! */ 1054*7c478bd9Sstevel@tonic-gate static int 1055*7c478bd9Sstevel@tonic-gate cldap_select1( LDAP *ld, struct timeval *timeout ) 1056*7c478bd9Sstevel@tonic-gate { 1057*7c478bd9Sstevel@tonic-gate int rc; 1058*7c478bd9Sstevel@tonic-gate static int tblsize = 0; 1059*7c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp = ld->ld_iostatus; 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate if ( tblsize == 0 ) { 1062*7c478bd9Sstevel@tonic-gate #ifdef USE_SYSCONF 1063*7c478bd9Sstevel@tonic-gate tblsize = sysconf( _SC_OPEN_MAX ); 1064*7c478bd9Sstevel@tonic-gate #else /* USE_SYSCONF */ 1065*7c478bd9Sstevel@tonic-gate tblsize = getdtablesize(); 1066*7c478bd9Sstevel@tonic-gate #endif /* USE_SYSCONF */ 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate if ( tblsize >= FD_SETSIZE ) { 1070*7c478bd9Sstevel@tonic-gate /* 1071*7c478bd9Sstevel@tonic-gate * clamp value so we don't overrun the fd_set structure 1072*7c478bd9Sstevel@tonic-gate */ 1073*7c478bd9Sstevel@tonic-gate tblsize = FD_SETSIZE - 1; 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate if ( NSLDAPI_IOSTATUS_TYPE_OSNATIVE == iosp->ios_type ) { 1077*7c478bd9Sstevel@tonic-gate fd_set readfds; 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate FD_ZERO( &readfds ); 1080*7c478bd9Sstevel@tonic-gate FD_SET( ld->ld_sbp->sb_sd, &readfds ); 1081*7c478bd9Sstevel@tonic-gate 1082*7c478bd9Sstevel@tonic-gate /* XXXmcs: UNIX platforms should use poll() */ 1083*7c478bd9Sstevel@tonic-gate rc = select( tblsize, &readfds, 0, 0, timeout ) ); 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate } else if ( NSLDAPI_IOSTATUS_TYPE_CALLBACK == iosp->ios_type ) { 1086*7c478bd9Sstevel@tonic-gate LDAP_X_PollFD pollfds[ 1 ]; 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate pollfds[0].lpoll_fd = ld->ld_sbp->sb_sd; 1089*7c478bd9Sstevel@tonic-gate pollfds[0].lpoll_arg = ld->ld_sbp->sb_arg; 1090*7c478bd9Sstevel@tonic-gate pollfds[0].lpoll_events = LDAP_X_POLLIN; 1091*7c478bd9Sstevel@tonic-gate pollfds[0].lpoll_revents = 0; 1092*7c478bd9Sstevel@tonic-gate rc = ld->ld_extpoll_fn( pollfds, 1, nsldapi_tv2ms( timeout ), 1093*7c478bd9Sstevel@tonic-gate ld->ld_ext_session_arg ); 1094*7c478bd9Sstevel@tonic-gate } else { 1095*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY, 1096*7c478bd9Sstevel@tonic-gate "nsldapi_iostatus_poll: unknown I/O type %d\n", 1097*7c478bd9Sstevel@tonic-gate rc = 0; /* simulate a timeout (what else to do?) */ 1098*7c478bd9Sstevel@tonic-gate } 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate return( rc ); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate #endif /* !macintosh */ 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate #ifdef macintosh 1106*7c478bd9Sstevel@tonic-gate static int 1107*7c478bd9Sstevel@tonic-gate cldap_select1( LDAP *ld, struct timeval *timeout ) 1108*7c478bd9Sstevel@tonic-gate { 1109*7c478bd9Sstevel@tonic-gate /* XXXmcs: needs to be revised to support I/O callbacks */ 1110*7c478bd9Sstevel@tonic-gate return( tcpselect( ld->ld_sbp->sb_sd, timeout )); 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate #endif /* macintosh */ 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate #if (defined( DOS ) && defined( WINSOCK )) || defined( _WINDOWS ) || defined(XP_OS2) 1116*7c478bd9Sstevel@tonic-gate /* XXXmcs: needs to be revised to support extended I/O callbacks */ 1117*7c478bd9Sstevel@tonic-gate static int 1118*7c478bd9Sstevel@tonic-gate cldap_select1( LDAP *ld, struct timeval *timeout ) 1119*7c478bd9Sstevel@tonic-gate { 1120*7c478bd9Sstevel@tonic-gate fd_set readfds; 1121*7c478bd9Sstevel@tonic-gate int rc; 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate FD_ZERO( &readfds ); 1124*7c478bd9Sstevel@tonic-gate FD_SET( ld->ld_sbp->sb_sd, &readfds ); 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate if ( NSLDAPI_IO_TYPE_STANDARD == ld->ldiou_type && 1127*7c478bd9Sstevel@tonic-gate NULL != ld->ld_select_fn ) { 1128*7c478bd9Sstevel@tonic-gate rc = ld->ld_select_fn( 1, &readfds, 0, 0, timeout ); 1129*7c478bd9Sstevel@tonic-gate } else if ( NSLDAPI_IO_TYPE_EXTENDED == ld->ldiou_type && 1130*7c478bd9Sstevel@tonic-gate NULL != ld->ld_extselect_fn ) { 1131*7c478bd9Sstevel@tonic-gate rc = ld->ld_extselect_fn( ld->ld_ext_session_arg, 1, &readfds, 0, 1132*7c478bd9Sstevel@tonic-gate 0, timeout ) ); 1133*7c478bd9Sstevel@tonic-gate } else { 1134*7c478bd9Sstevel@tonic-gate /* XXXmcs: UNIX platforms should use poll() */ 1135*7c478bd9Sstevel@tonic-gate rc = select( 1, &readfds, 0, 0, timeout ) ); 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate return( rc == SOCKET_ERROR ? -1 : rc ); 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate #endif /* WINSOCK || _WINDOWS */ 1141*7c478bd9Sstevel@tonic-gate #endif /* CLDAP */ 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate int 1144*7c478bd9Sstevel@tonic-gate LDAP_CALL 1145*7c478bd9Sstevel@tonic-gate ldap_msgfree( LDAPMessage *lm ) 1146*7c478bd9Sstevel@tonic-gate { 1147*7c478bd9Sstevel@tonic-gate LDAPMessage *next; 1148*7c478bd9Sstevel@tonic-gate int type = 0; 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate for ( ; lm != NULL; lm = next ) { 1153*7c478bd9Sstevel@tonic-gate next = lm->lm_chain; 1154*7c478bd9Sstevel@tonic-gate type = lm->lm_msgtype; 1155*7c478bd9Sstevel@tonic-gate ber_free( lm->lm_ber, 1 ); 1156*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char *) lm ); 1157*7c478bd9Sstevel@tonic-gate } 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate return( type ); 1160*7c478bd9Sstevel@tonic-gate } 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate /* 1163*7c478bd9Sstevel@tonic-gate * ldap_msgdelete - delete a message. It returns: 1164*7c478bd9Sstevel@tonic-gate * 0 if the entire message was deleted 1165*7c478bd9Sstevel@tonic-gate * -1 if the message was not found, or only part of it was found 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate int 1168*7c478bd9Sstevel@tonic-gate ldap_msgdelete( LDAP *ld, int msgid ) 1169*7c478bd9Sstevel@tonic-gate { 1170*7c478bd9Sstevel@tonic-gate LDAPMessage *lm, *prev; 1171*7c478bd9Sstevel@tonic-gate int msgtype; 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 ); 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 1176*7c478bd9Sstevel@tonic-gate return( -1 ); /* punt */ 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate prev = NULL; 1180*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); 1181*7c478bd9Sstevel@tonic-gate for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { 1182*7c478bd9Sstevel@tonic-gate if ( lm->lm_msgid == msgid ) 1183*7c478bd9Sstevel@tonic-gate break; 1184*7c478bd9Sstevel@tonic-gate prev = lm; 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate if ( lm == NULL ) 1188*7c478bd9Sstevel@tonic-gate { 1189*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 1190*7c478bd9Sstevel@tonic-gate return( -1 ); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate if ( prev == NULL ) 1194*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 1195*7c478bd9Sstevel@tonic-gate else 1196*7c478bd9Sstevel@tonic-gate prev->lm_next = lm->lm_next; 1197*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate msgtype = ldap_msgfree( lm ); 1200*7c478bd9Sstevel@tonic-gate if ( msgtype == LDAP_RES_SEARCH_ENTRY 1201*7c478bd9Sstevel@tonic-gate || msgtype == LDAP_RES_SEARCH_REFERENCE ) { 1202*7c478bd9Sstevel@tonic-gate return( -1 ); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate return( 0 ); 1206*7c478bd9Sstevel@tonic-gate } 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate /* 1210*7c478bd9Sstevel@tonic-gate * return 1 if message msgid is waiting to be abandoned, 0 otherwise 1211*7c478bd9Sstevel@tonic-gate */ 1212*7c478bd9Sstevel@tonic-gate static int 1213*7c478bd9Sstevel@tonic-gate ldap_abandoned( LDAP *ld, int msgid ) 1214*7c478bd9Sstevel@tonic-gate { 1215*7c478bd9Sstevel@tonic-gate int i; 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); 1218*7c478bd9Sstevel@tonic-gate if ( ld->ld_abandoned == NULL ) 1219*7c478bd9Sstevel@tonic-gate { 1220*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1221*7c478bd9Sstevel@tonic-gate return( 0 ); 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) 1225*7c478bd9Sstevel@tonic-gate if ( ld->ld_abandoned[i] == msgid ) 1226*7c478bd9Sstevel@tonic-gate { 1227*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1228*7c478bd9Sstevel@tonic-gate return( 1 ); 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1232*7c478bd9Sstevel@tonic-gate return( 0 ); 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate static int 1237*7c478bd9Sstevel@tonic-gate ldap_mark_abandoned( LDAP *ld, int msgid ) 1238*7c478bd9Sstevel@tonic-gate { 1239*7c478bd9Sstevel@tonic-gate int i; 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); 1242*7c478bd9Sstevel@tonic-gate if ( ld->ld_abandoned == NULL ) 1243*7c478bd9Sstevel@tonic-gate { 1244*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1245*7c478bd9Sstevel@tonic-gate return( -1 ); 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) 1249*7c478bd9Sstevel@tonic-gate if ( ld->ld_abandoned[i] == msgid ) 1250*7c478bd9Sstevel@tonic-gate break; 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate if ( ld->ld_abandoned[i] == -1 ) 1253*7c478bd9Sstevel@tonic-gate { 1254*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1255*7c478bd9Sstevel@tonic-gate return( -1 ); 1256*7c478bd9Sstevel@tonic-gate } 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate for ( ; ld->ld_abandoned[i] != -1; i++ ) { 1259*7c478bd9Sstevel@tonic-gate ld->ld_abandoned[i] = ld->ld_abandoned[i + 1]; 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); 1263*7c478bd9Sstevel@tonic-gate return( 0 ); 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate #ifdef CLDAP 1268*7c478bd9Sstevel@tonic-gate int 1269*7c478bd9Sstevel@tonic-gate cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement **ber ) 1270*7c478bd9Sstevel@tonic-gate { 1271*7c478bd9Sstevel@tonic-gate int rc; 1272*7c478bd9Sstevel@tonic-gate ber_tag_t tag; 1273*7c478bd9Sstevel@tonic-gate ber_len_t len; 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate if ( ld->ld_sbp->sb_ber.ber_ptr >= ld->ld_sbp->sb_ber.ber_end ) { 1276*7c478bd9Sstevel@tonic-gate rc = cldap_select1( ld, timeout ); 1277*7c478bd9Sstevel@tonic-gate if ( rc == -1 || rc == 0 ) { 1278*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, (rc == -1 ? LDAP_SERVER_DOWN : 1279*7c478bd9Sstevel@tonic-gate LDAP_TIMEOUT), NULL, NULL ); 1280*7c478bd9Sstevel@tonic-gate return( rc ); 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate /* get the next message */ 1285*7c478bd9Sstevel@tonic-gate if ( (tag = ber_get_next( ld->ld_sbp, &len, ber )) 1286*7c478bd9Sstevel@tonic-gate != LDAP_TAG_MESSAGE ) { 1287*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : 1288*7c478bd9Sstevel@tonic-gate LDAP_LOCAL_ERROR), NULL, NULL ); 1289*7c478bd9Sstevel@tonic-gate return( -1 ); 1290*7c478bd9Sstevel@tonic-gate } 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate return( tag ); 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate #endif /* CLDAP */ 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate int 1297*7c478bd9Sstevel@tonic-gate nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result ) 1298*7c478bd9Sstevel@tonic-gate { 1299*7c478bd9Sstevel@tonic-gate LDAPPend *lp; 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, 1302*7c478bd9Sstevel@tonic-gate "nsldapi_post_result(ld=0x%x, msgid=%d, result=0x%x)\n", 1303*7c478bd9Sstevel@tonic-gate ld, msgid, result ); 1304*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_PEND_LOCK ); 1305*7c478bd9Sstevel@tonic-gate if( msgid == LDAP_RES_ANY ) { 1306*7c478bd9Sstevel@tonic-gate /* 1307*7c478bd9Sstevel@tonic-gate * Look for any pending request for which someone is waiting. 1308*7c478bd9Sstevel@tonic-gate */ 1309*7c478bd9Sstevel@tonic-gate for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) 1310*7c478bd9Sstevel@tonic-gate { 1311*7c478bd9Sstevel@tonic-gate if ( lp->lp_sema != NULL ) { 1312*7c478bd9Sstevel@tonic-gate break; 1313*7c478bd9Sstevel@tonic-gate } 1314*7c478bd9Sstevel@tonic-gate } 1315*7c478bd9Sstevel@tonic-gate /* 1316*7c478bd9Sstevel@tonic-gate * If we did't find a pending request, lp is NULL at this 1317*7c478bd9Sstevel@tonic-gate * point, and we will leave this function without doing 1318*7c478bd9Sstevel@tonic-gate * anything more -- which is exactly what we want to do. 1319*7c478bd9Sstevel@tonic-gate */ 1320*7c478bd9Sstevel@tonic-gate } 1321*7c478bd9Sstevel@tonic-gate else 1322*7c478bd9Sstevel@tonic-gate { 1323*7c478bd9Sstevel@tonic-gate /* 1324*7c478bd9Sstevel@tonic-gate * Look for a pending request specific to this message id 1325*7c478bd9Sstevel@tonic-gate */ 1326*7c478bd9Sstevel@tonic-gate for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) 1327*7c478bd9Sstevel@tonic-gate { 1328*7c478bd9Sstevel@tonic-gate if( lp->lp_msgid == msgid ) 1329*7c478bd9Sstevel@tonic-gate break; 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate if( lp == NULL ) 1333*7c478bd9Sstevel@tonic-gate { 1334*7c478bd9Sstevel@tonic-gate /* 1335*7c478bd9Sstevel@tonic-gate * No pending requests for this response... append to 1336*7c478bd9Sstevel@tonic-gate * our pending result list. 1337*7c478bd9Sstevel@tonic-gate */ 1338*7c478bd9Sstevel@tonic-gate LDAPPend *newlp; 1339*7c478bd9Sstevel@tonic-gate newlp = (LDAPPend *)NSLDAPI_CALLOC( 1, 1340*7c478bd9Sstevel@tonic-gate sizeof( LDAPPend )); 1341*7c478bd9Sstevel@tonic-gate if( newlp == NULL ) 1342*7c478bd9Sstevel@tonic-gate { 1343*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); 1344*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, 1345*7c478bd9Sstevel@tonic-gate NULL ); 1346*7c478bd9Sstevel@tonic-gate return (-1); 1347*7c478bd9Sstevel@tonic-gate } 1348*7c478bd9Sstevel@tonic-gate newlp->lp_msgid = msgid; 1349*7c478bd9Sstevel@tonic-gate newlp->lp_result = result; 1350*7c478bd9Sstevel@tonic-gate link_pend( ld, newlp ); 1351*7c478bd9Sstevel@tonic-gate } 1352*7c478bd9Sstevel@tonic-gate } 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate if( lp != NULL ) 1356*7c478bd9Sstevel@tonic-gate { 1357*7c478bd9Sstevel@tonic-gate /* 1358*7c478bd9Sstevel@tonic-gate * Wake up a thread that is waiting for this result. 1359*7c478bd9Sstevel@tonic-gate */ 1360*7c478bd9Sstevel@tonic-gate lp->lp_msgid = msgid; 1361*7c478bd9Sstevel@tonic-gate lp->lp_result = result; 1362*7c478bd9Sstevel@tonic-gate LDAP_SEMA_POST( ld, lp ); 1363*7c478bd9Sstevel@tonic-gate } 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); 1366*7c478bd9Sstevel@tonic-gate return (0); 1367*7c478bd9Sstevel@tonic-gate } 1368*7c478bd9Sstevel@tonic-gate 1369*7c478bd9Sstevel@tonic-gate static void 1370*7c478bd9Sstevel@tonic-gate link_pend( LDAP *ld, LDAPPend *lp ) 1371*7c478bd9Sstevel@tonic-gate { 1372*7c478bd9Sstevel@tonic-gate if (( lp->lp_next = ld->ld_pend ) != NULL ) 1373*7c478bd9Sstevel@tonic-gate { 1374*7c478bd9Sstevel@tonic-gate lp->lp_next->lp_prev = lp; 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate ld->ld_pend = lp; 1377*7c478bd9Sstevel@tonic-gate lp->lp_prev = NULL; 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate #if 0 /* these functions are no longer used */ 1381*7c478bd9Sstevel@tonic-gate static void 1382*7c478bd9Sstevel@tonic-gate unlink_pend( LDAP *ld, LDAPPend *lp ) 1383*7c478bd9Sstevel@tonic-gate { 1384*7c478bd9Sstevel@tonic-gate if ( lp->lp_prev == NULL ) { 1385*7c478bd9Sstevel@tonic-gate ld->ld_pend = lp->lp_next; 1386*7c478bd9Sstevel@tonic-gate } else { 1387*7c478bd9Sstevel@tonic-gate lp->lp_prev->lp_next = lp->lp_next; 1388*7c478bd9Sstevel@tonic-gate } 1389*7c478bd9Sstevel@tonic-gate 1390*7c478bd9Sstevel@tonic-gate if ( lp->lp_next != NULL ) { 1391*7c478bd9Sstevel@tonic-gate lp->lp_next->lp_prev = lp->lp_prev; 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate static int 1396*7c478bd9Sstevel@tonic-gate unlink_msg( LDAP *ld, int msgid, int all ) 1397*7c478bd9Sstevel@tonic-gate { 1398*7c478bd9Sstevel@tonic-gate int rc; 1399*7c478bd9Sstevel@tonic-gate LDAPMessage *lm, *lastlm, *nextlm; 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate lastlm = NULL; 1402*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); 1403*7c478bd9Sstevel@tonic-gate for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) 1404*7c478bd9Sstevel@tonic-gate { 1405*7c478bd9Sstevel@tonic-gate nextlm = lm->lm_next; 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate if ( lm->lm_msgid == msgid ) 1408*7c478bd9Sstevel@tonic-gate { 1409*7c478bd9Sstevel@tonic-gate LDAPMessage *tmp; 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate if ( all == 0 1412*7c478bd9Sstevel@tonic-gate || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT 1413*7c478bd9Sstevel@tonic-gate && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE 1414*7c478bd9Sstevel@tonic-gate && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) 1415*7c478bd9Sstevel@tonic-gate break; 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { 1418*7c478bd9Sstevel@tonic-gate if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) 1419*7c478bd9Sstevel@tonic-gate break; 1420*7c478bd9Sstevel@tonic-gate } 1421*7c478bd9Sstevel@tonic-gate if( tmp != NULL ) 1422*7c478bd9Sstevel@tonic-gate break; 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate lastlm = lm; 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate if( lm != NULL ) 1428*7c478bd9Sstevel@tonic-gate { 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate if ( all == 0 ) 1431*7c478bd9Sstevel@tonic-gate { 1432*7c478bd9Sstevel@tonic-gate if ( lm->lm_chain == NULL ) 1433*7c478bd9Sstevel@tonic-gate { 1434*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) 1435*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 1436*7c478bd9Sstevel@tonic-gate else 1437*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_next; 1438*7c478bd9Sstevel@tonic-gate } 1439*7c478bd9Sstevel@tonic-gate else 1440*7c478bd9Sstevel@tonic-gate { 1441*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) 1442*7c478bd9Sstevel@tonic-gate { 1443*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_chain; 1444*7c478bd9Sstevel@tonic-gate ld->ld_responses->lm_next = lm->lm_next; 1445*7c478bd9Sstevel@tonic-gate } 1446*7c478bd9Sstevel@tonic-gate else 1447*7c478bd9Sstevel@tonic-gate { 1448*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_chain; 1449*7c478bd9Sstevel@tonic-gate lastlm->lm_next->lm_next = lm->lm_next; 1450*7c478bd9Sstevel@tonic-gate } 1451*7c478bd9Sstevel@tonic-gate } 1452*7c478bd9Sstevel@tonic-gate } 1453*7c478bd9Sstevel@tonic-gate else 1454*7c478bd9Sstevel@tonic-gate { 1455*7c478bd9Sstevel@tonic-gate if ( lastlm == NULL ) 1456*7c478bd9Sstevel@tonic-gate ld->ld_responses = lm->lm_next; 1457*7c478bd9Sstevel@tonic-gate else 1458*7c478bd9Sstevel@tonic-gate lastlm->lm_next = lm->lm_next; 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate if ( all == 0 ) 1462*7c478bd9Sstevel@tonic-gate lm->lm_chain = NULL; 1463*7c478bd9Sstevel@tonic-gate lm->lm_next = NULL; 1464*7c478bd9Sstevel@tonic-gate rc = lm->lm_msgtype; 1465*7c478bd9Sstevel@tonic-gate } 1466*7c478bd9Sstevel@tonic-gate else 1467*7c478bd9Sstevel@tonic-gate { 1468*7c478bd9Sstevel@tonic-gate rc = -2; 1469*7c478bd9Sstevel@tonic-gate } 1470*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); 1471*7c478bd9Sstevel@tonic-gate return ( rc ); 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 1474