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