xref: /onnv-gate/usr/src/lib/libldap4/common/request.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 1998-2002 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 /*
9*0Sstevel@tonic-gate  *  Copyright (c) 1995 Regents of the University of Michigan.
10*0Sstevel@tonic-gate  *  All rights reserved.
11*0Sstevel@tonic-gate  *
12*0Sstevel@tonic-gate  *  request.c - sending of ldap requests; handling of referrals
13*0Sstevel@tonic-gate  */
14*0Sstevel@tonic-gate 
15*0Sstevel@tonic-gate #ifndef lint
16*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
17*0Sstevel@tonic-gate #endif
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate #include <stdio.h>
20*0Sstevel@tonic-gate #include <string.h>
21*0Sstevel@tonic-gate #ifdef MACOS
22*0Sstevel@tonic-gate #include <stdlib.h>
23*0Sstevel@tonic-gate #include <time.h>
24*0Sstevel@tonic-gate #include "macos.h"
25*0Sstevel@tonic-gate #else /* MACOS */
26*0Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 )
27*0Sstevel@tonic-gate #include "msdos.h"
28*0Sstevel@tonic-gate #include <time.h>
29*0Sstevel@tonic-gate #include <stdlib.h>
30*0Sstevel@tonic-gate #ifdef PCNFS
31*0Sstevel@tonic-gate #include <tklib.h>
32*0Sstevel@tonic-gate #include <tk_errno.h>
33*0Sstevel@tonic-gate #include <bios.h>
34*0Sstevel@tonic-gate #endif /* PCNFS */
35*0Sstevel@tonic-gate #ifdef NCSA
36*0Sstevel@tonic-gate #include "externs.h"
37*0Sstevel@tonic-gate #endif /* NCSA */
38*0Sstevel@tonic-gate #else /* DOS */
39*0Sstevel@tonic-gate #include <sys/time.h>
40*0Sstevel@tonic-gate #include <sys/types.h>
41*0Sstevel@tonic-gate #include <sys/socket.h>
42*0Sstevel@tonic-gate #include <errno.h>
43*0Sstevel@tonic-gate #ifdef _AIX
44*0Sstevel@tonic-gate #include <sys/select.h>
45*0Sstevel@tonic-gate #endif /* _AIX */
46*0Sstevel@tonic-gate #include "portable.h"
47*0Sstevel@tonic-gate #endif /* DOS */
48*0Sstevel@tonic-gate #endif /* MACOS */
49*0Sstevel@tonic-gate #ifdef VMS
50*0Sstevel@tonic-gate #include "ucx_select.h"
51*0Sstevel@tonic-gate #endif
52*0Sstevel@tonic-gate #include "lber.h"
53*0Sstevel@tonic-gate #include "ldap.h"
54*0Sstevel@tonic-gate #include "ldap-private.h"
55*0Sstevel@tonic-gate #include "ldap-int.h"
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate #ifdef USE_SYSCONF
58*0Sstevel@tonic-gate #include <unistd.h>
59*0Sstevel@tonic-gate #endif /* USE_SYSCONF */
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate #ifdef NEEDPROTOS
62*0Sstevel@tonic-gate static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
63*0Sstevel@tonic-gate static void use_connection( LDAP *ld, LDAPConn *lc );
64*0Sstevel@tonic-gate static void free_servers( LDAPServer *srvlist );
65*0Sstevel@tonic-gate #else /* NEEDPROTOS */
66*0Sstevel@tonic-gate static LDAPConn *find_connection();
67*0Sstevel@tonic-gate static void use_connection();
68*0Sstevel@tonic-gate static void free_servers();
69*0Sstevel@tonic-gate #endif /* NEEDPROTOS */
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate #ifdef LDAP_DNS
73*0Sstevel@tonic-gate #ifdef NEEDPROTOS
74*0Sstevel@tonic-gate static LDAPServer *dn2servers( LDAP *ld, char *dn );
75*0Sstevel@tonic-gate #else /* NEEDPROTOS */
76*0Sstevel@tonic-gate static LDAPServer *dn2servers();
77*0Sstevel@tonic-gate #endif /* NEEDPROTOS */
78*0Sstevel@tonic-gate #endif /* LDAP_DNS */
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate BerElement *
alloc_ber_with_options(LDAP * ld)82*0Sstevel@tonic-gate alloc_ber_with_options( LDAP *ld )
83*0Sstevel@tonic-gate {
84*0Sstevel@tonic-gate 	BerElement	*ber;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate     	if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
87*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
88*0Sstevel@tonic-gate #ifdef STR_TRANSLATION
89*0Sstevel@tonic-gate 	} else {
90*0Sstevel@tonic-gate 		set_ber_options( ld, ber );
91*0Sstevel@tonic-gate #endif /* STR_TRANSLATION */
92*0Sstevel@tonic-gate 	}
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	return( ber );
95*0Sstevel@tonic-gate }
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate void
set_ber_options(LDAP * ld,BerElement * ber)99*0Sstevel@tonic-gate set_ber_options( LDAP *ld, BerElement *ber )
100*0Sstevel@tonic-gate {
101*0Sstevel@tonic-gate 	ber->ber_options = ld->ld_lberoptions;
102*0Sstevel@tonic-gate #ifdef STR_TRANSLATION
103*0Sstevel@tonic-gate 	if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) {
104*0Sstevel@tonic-gate 		ber_set_string_translators( ber,
105*0Sstevel@tonic-gate 		    ld->ld_lber_encode_translate_proc,
106*0Sstevel@tonic-gate 		    ld->ld_lber_decode_translate_proc );
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate #endif /* STR_TRANSLATION */
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate int
send_initial_request(LDAP * ld,unsigned int msgtype,char * dn,BerElement * ber)113*0Sstevel@tonic-gate send_initial_request( LDAP *ld, unsigned int msgtype, char *dn,
114*0Sstevel@tonic-gate 	BerElement *ber )
115*0Sstevel@tonic-gate {
116*0Sstevel@tonic-gate 	LDAPServer	*servers;
117*0Sstevel@tonic-gate 	int rv;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate #ifdef _REENTRANT
120*0Sstevel@tonic-gate         LOCK_LDAP(ld);
121*0Sstevel@tonic-gate #endif
122*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 209, "send_initial_request\n"), 0, 0, 0 );
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate #ifdef LDAP_DNS
125*0Sstevel@tonic-gate 	if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
126*0Sstevel@tonic-gate 		if (( servers = dn2servers( ld, dn )) == NULL ) {
127*0Sstevel@tonic-gate 			ber_free( ber, 1 );
128*0Sstevel@tonic-gate #ifdef _REENTRANT
129*0Sstevel@tonic-gate 			UNLOCK_LDAP(ld);
130*0Sstevel@tonic-gate #endif
131*0Sstevel@tonic-gate 			return( -1 );
132*0Sstevel@tonic-gate 		}
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
135*0Sstevel@tonic-gate 		if ( ldap_debug & LDAP_DEBUG_TRACE ) {
136*0Sstevel@tonic-gate 			LDAPServer	*srv;
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 			for ( srv = servers; srv != NULL;
139*0Sstevel@tonic-gate 			    srv = srv->lsrv_next ) {
140*0Sstevel@tonic-gate 				fprintf( stderr,
141*0Sstevel@tonic-gate 				    "LDAP server %s:  dn %s, port %d\n",
142*0Sstevel@tonic-gate 				    srv->lsrv_host, ( srv->lsrv_dn == NULL ) ?
143*0Sstevel@tonic-gate 				    "(default)" : srv->lsrv_dn,
144*0Sstevel@tonic-gate 				    srv->lsrv_port );
145*0Sstevel@tonic-gate 			}
146*0Sstevel@tonic-gate 		}
147*0Sstevel@tonic-gate #endif /* LDAP_DEBUG */
148*0Sstevel@tonic-gate 	} else {
149*0Sstevel@tonic-gate #endif /* LDAP_DNS */
150*0Sstevel@tonic-gate 		/*
151*0Sstevel@tonic-gate 		 * use of DNS is turned off or this is an X.500 DN...
152*0Sstevel@tonic-gate 		 * use our default connection
153*0Sstevel@tonic-gate 		 */
154*0Sstevel@tonic-gate 		servers = NULL;
155*0Sstevel@tonic-gate #ifdef LDAP_DNS
156*0Sstevel@tonic-gate 	}
157*0Sstevel@tonic-gate #endif /* LDAP_DNS */
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate #ifdef _REENTRANT
160*0Sstevel@tonic-gate     UNLOCK_LDAP(ld);
161*0Sstevel@tonic-gate #endif
162*0Sstevel@tonic-gate 	rv = send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
163*0Sstevel@tonic-gate 							  NULL, 0 );
164*0Sstevel@tonic-gate 	return ( rv );
165*0Sstevel@tonic-gate }
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate int
send_server_request(LDAP * ld,BerElement * ber,int msgid,LDAPRequest * parentreq,LDAPServer * srvlist,LDAPConn * lc,int bind)168*0Sstevel@tonic-gate send_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
169*0Sstevel@tonic-gate 	*parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
170*0Sstevel@tonic-gate {
171*0Sstevel@tonic-gate 	LDAPRequest	*lr;
172*0Sstevel@tonic-gate 	int err;
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate #ifdef _REENTRANT
175*0Sstevel@tonic-gate         LOCK_LDAP(ld);
176*0Sstevel@tonic-gate #endif
177*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 210, "send_server_request\n"), 0, 0, 0 );
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	ld->ld_errno = LDAP_SUCCESS;	/* optimistic */
180*0Sstevel@tonic-gate 	/* Be optimistic : increment parentreq initially.
181*0Sstevel@tonic-gate 	   If it fails we must decrement it */
182*0Sstevel@tonic-gate 	if (parentreq != NULL){
183*0Sstevel@tonic-gate 		parentreq->lr_outrefcnt++;
184*0Sstevel@tonic-gate 	}
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	if ( lc == NULL ) {
187*0Sstevel@tonic-gate 		if ( srvlist == NULL ) {
188*0Sstevel@tonic-gate 			if  (ld->ld_defconn == NULL){ /* Not connected yet on the default connection, ie init was called not open */
189*0Sstevel@tonic-gate 				if ((err = open_default_ldap_connection(ld)) != LDAP_SUCCESS){
190*0Sstevel@tonic-gate 					ld->ld_errno = err;
191*0Sstevel@tonic-gate 					ber_free(ber, 1);
192*0Sstevel@tonic-gate 					if (parentreq != NULL){
193*0Sstevel@tonic-gate 						parentreq->lr_outrefcnt--;
194*0Sstevel@tonic-gate 					}
195*0Sstevel@tonic-gate #ifdef _REENTRANT
196*0Sstevel@tonic-gate 					UNLOCK_LDAP(ld);
197*0Sstevel@tonic-gate #endif
198*0Sstevel@tonic-gate 					return( -1 );
199*0Sstevel@tonic-gate 				}
200*0Sstevel@tonic-gate 			}
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 			lc = ld->ld_defconn;
203*0Sstevel@tonic-gate 		} else {
204*0Sstevel@tonic-gate 			if (( lc = find_connection( ld, srvlist, 1 )) ==
205*0Sstevel@tonic-gate 			    NULL ) {
206*0Sstevel@tonic-gate 				lc = new_connection( ld, &srvlist, 0, 1, bind );
207*0Sstevel@tonic-gate 			}
208*0Sstevel@tonic-gate 			free_servers( srvlist );
209*0Sstevel@tonic-gate 		}
210*0Sstevel@tonic-gate 	}
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
213*0Sstevel@tonic-gate 		ber_free( ber, 1 );
214*0Sstevel@tonic-gate 		if ( ld->ld_errno == LDAP_SUCCESS ) {
215*0Sstevel@tonic-gate 			ld->ld_errno = LDAP_SERVER_DOWN;
216*0Sstevel@tonic-gate 		}
217*0Sstevel@tonic-gate 		if (parentreq != NULL){
218*0Sstevel@tonic-gate 			parentreq->lr_outrefcnt--;
219*0Sstevel@tonic-gate 		}
220*0Sstevel@tonic-gate #ifdef _REENTRANT
221*0Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
222*0Sstevel@tonic-gate #endif
223*0Sstevel@tonic-gate 		return( -1 );
224*0Sstevel@tonic-gate 	}
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	use_connection( ld, lc );
227*0Sstevel@tonic-gate 	if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
228*0Sstevel@tonic-gate 	    NULL ) {
229*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
230*0Sstevel@tonic-gate 		free_connection( ld, lc, 0, 0 );
231*0Sstevel@tonic-gate 		ber_free( ber, 1 );
232*0Sstevel@tonic-gate #ifdef _REENTRANT
233*0Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
234*0Sstevel@tonic-gate #endif
235*0Sstevel@tonic-gate 		return( -1 );
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 	lr->lr_msgid = msgid;
238*0Sstevel@tonic-gate 	lr->lr_status = LDAP_REQST_INPROGRESS;
239*0Sstevel@tonic-gate 	lr->lr_res_errno = LDAP_SUCCESS;	/* optimistic */
240*0Sstevel@tonic-gate 	lr->lr_ber = ber;
241*0Sstevel@tonic-gate 	lr->lr_conn = lc;
242*0Sstevel@tonic-gate 	if ( parentreq != NULL ) {	/* sub-request */
243*0Sstevel@tonic-gate /* 		++parentreq->lr_outrefcnt; */
244*0Sstevel@tonic-gate 		lr->lr_origid = parentreq->lr_origid;
245*0Sstevel@tonic-gate 		lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
246*0Sstevel@tonic-gate 		lr->lr_parent = parentreq;
247*0Sstevel@tonic-gate 		lr->lr_refnext = parentreq->lr_refnext;
248*0Sstevel@tonic-gate 		parentreq->lr_refnext = lr;
249*0Sstevel@tonic-gate 	} else {			/* original request */
250*0Sstevel@tonic-gate 		lr->lr_origid = lr->lr_msgid;
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	if (( lr->lr_next = ld->ld_requests ) != NULL ) {
254*0Sstevel@tonic-gate 		lr->lr_next->lr_prev = lr;
255*0Sstevel@tonic-gate 	}
256*0Sstevel@tonic-gate 	ld->ld_requests = lr;
257*0Sstevel@tonic-gate 	lr->lr_prev = NULL;
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
260*0Sstevel@tonic-gate #ifdef notyet
261*0Sstevel@tonic-gate 		extern int	errno;
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 		if ( errno == EWOULDBLOCK ) {
264*0Sstevel@tonic-gate 			/* need to continue write later */
265*0Sstevel@tonic-gate 			lr->lr_status = LDAP_REQST_WRITING;
266*0Sstevel@tonic-gate 			mark_select_write( ld, lc->lconn_sb );
267*0Sstevel@tonic-gate 		} else {
268*0Sstevel@tonic-gate #else /* notyet */
269*0Sstevel@tonic-gate 			ld->ld_errno = LDAP_SERVER_DOWN;
270*0Sstevel@tonic-gate 			free_request( ld, lr );
271*0Sstevel@tonic-gate 			free_connection( ld, lc, 0, 0 );
272*0Sstevel@tonic-gate #ifdef _REENTRANT
273*0Sstevel@tonic-gate 			UNLOCK_LDAP(ld);
274*0Sstevel@tonic-gate #endif
275*0Sstevel@tonic-gate 			return( -1 );
276*0Sstevel@tonic-gate #endif /* notyet */
277*0Sstevel@tonic-gate #ifdef notyet
278*0Sstevel@tonic-gate 		}
279*0Sstevel@tonic-gate #endif /* notyet */
280*0Sstevel@tonic-gate 	} else {
281*0Sstevel@tonic-gate 		if ( parentreq == NULL ) {
282*0Sstevel@tonic-gate 			ber->ber_end = ber->ber_ptr;
283*0Sstevel@tonic-gate 			ber->ber_ptr = ber->ber_buf;
284*0Sstevel@tonic-gate 		}
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 		/* sent -- waiting for a response */
287*0Sstevel@tonic-gate 		mark_select_read( ld, lc->lconn_sb );
288*0Sstevel@tonic-gate 	}
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate 	ld->ld_errno = LDAP_SUCCESS;
291*0Sstevel@tonic-gate #ifdef _REENTRANT
292*0Sstevel@tonic-gate         UNLOCK_LDAP(ld);
293*0Sstevel@tonic-gate #endif
294*0Sstevel@tonic-gate 	return( msgid );
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate LDAPConn *
new_connection(LDAP * ld,LDAPServer ** srvlistp,int use_ldsb,int connect,int bind)299*0Sstevel@tonic-gate new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
300*0Sstevel@tonic-gate 	int connect, int bind )
301*0Sstevel@tonic-gate {
302*0Sstevel@tonic-gate 	LDAPConn	*lc;
303*0Sstevel@tonic-gate 	LDAPServer	*prevsrv, *srv;
304*0Sstevel@tonic-gate 	Sockbuf		*sb;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	/*
307*0Sstevel@tonic-gate 	 * make a new LDAP server connection
308*0Sstevel@tonic-gate 	 * XXX open connection synchronously for now
309*0Sstevel@tonic-gate 	 */
310*0Sstevel@tonic-gate 	if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
311*0Sstevel@tonic-gate 	    ( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
312*0Sstevel@tonic-gate 	    == NULL )) {
313*0Sstevel@tonic-gate 		if ( lc != NULL ) {
314*0Sstevel@tonic-gate 			free( (char *)lc );
315*0Sstevel@tonic-gate 		}
316*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
317*0Sstevel@tonic-gate 		return( NULL );
318*0Sstevel@tonic-gate 	}
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate #ifdef _REENTRANT
321*0Sstevel@tonic-gate 	LOCK_LDAP(ld);
322*0Sstevel@tonic-gate #endif
323*0Sstevel@tonic-gate 	lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	if ( connect ) {
326*0Sstevel@tonic-gate 		prevsrv = NULL;
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 		for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) {
329*0Sstevel@tonic-gate 			if ( open_ldap_connection( ld, lc->lconn_sb,
330*0Sstevel@tonic-gate 			    srv->lsrv_host, srv->lsrv_port,
331*0Sstevel@tonic-gate 			    &lc->lconn_krbinstance, 0 ) != -1 ) {
332*0Sstevel@tonic-gate 				break;
333*0Sstevel@tonic-gate 			}
334*0Sstevel@tonic-gate 			prevsrv = srv;
335*0Sstevel@tonic-gate 		}
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 		if ( srv == NULL ) {
338*0Sstevel@tonic-gate 		    if ( !use_ldsb ) {
339*0Sstevel@tonic-gate 				free( (char *)lc->lconn_sb );
340*0Sstevel@tonic-gate 		    }
341*0Sstevel@tonic-gate 		    free( (char *)lc );
342*0Sstevel@tonic-gate 		    ld->ld_errno = LDAP_SERVER_DOWN;
343*0Sstevel@tonic-gate #ifdef _REENTRANT
344*0Sstevel@tonic-gate 		    UNLOCK_LDAP(ld);
345*0Sstevel@tonic-gate #endif
346*0Sstevel@tonic-gate 		    return( NULL );
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 		if ( prevsrv == NULL ) {
350*0Sstevel@tonic-gate 		    *srvlistp = srv->lsrv_next;
351*0Sstevel@tonic-gate 		} else {
352*0Sstevel@tonic-gate 		    prevsrv->lsrv_next = srv->lsrv_next;
353*0Sstevel@tonic-gate 		}
354*0Sstevel@tonic-gate 		lc->lconn_server = srv;
355*0Sstevel@tonic-gate 	}
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 	lc->lconn_status = LDAP_CONNST_CONNECTED;
358*0Sstevel@tonic-gate 	lc->lconn_next = ld->ld_conns;
359*0Sstevel@tonic-gate 	ld->ld_conns = lc;
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	/*
362*0Sstevel@tonic-gate 	 * XXX for now, we always do a synchronous bind.  This will have
363*0Sstevel@tonic-gate 	 * to change in the long run...
364*0Sstevel@tonic-gate 	 */
365*0Sstevel@tonic-gate 	if ( bind ) {
366*0Sstevel@tonic-gate 		int		err, freepasswd, authmethod;
367*0Sstevel@tonic-gate 		char		*binddn, *passwd;
368*0Sstevel@tonic-gate 		LDAPConn	*savedefconn;
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 		freepasswd = err = 0;
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 		if ( ld->ld_version == LDAP_VERSION3 && ld->ld_rebindproc == NULL){
373*0Sstevel@tonic-gate 			/* Nothing to do */
374*0Sstevel@tonic-gate 			Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1280, "new_connection: bind no needed with ldapv3\n"), 0,0,0);
375*0Sstevel@tonic-gate 		} else {
376*0Sstevel@tonic-gate 			if ( ld->ld_rebindproc == NULL ) {
377*0Sstevel@tonic-gate 				binddn = passwd = "";
378*0Sstevel@tonic-gate 				authmethod = LDAP_AUTH_SIMPLE;
379*0Sstevel@tonic-gate 			} else {
380*0Sstevel@tonic-gate 				if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd,
381*0Sstevel@tonic-gate 												  &authmethod, 0, ld->ld_rebind_extra_arg )) == LDAP_SUCCESS ) {
382*0Sstevel@tonic-gate 					freepasswd = 1;
383*0Sstevel@tonic-gate 				} else {
384*0Sstevel@tonic-gate 					ld->ld_errno = err;
385*0Sstevel@tonic-gate 					err = -1;
386*0Sstevel@tonic-gate 				}
387*0Sstevel@tonic-gate 			}
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 			if ( err == 0 ) {
390*0Sstevel@tonic-gate 				savedefconn = ld->ld_defconn;
391*0Sstevel@tonic-gate 				ld->ld_defconn = lc;
392*0Sstevel@tonic-gate 				++lc->lconn_refcnt;	/* avoid premature free */
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 				if ( ldap_bind_s( ld, binddn, passwd, authmethod ) !=
395*0Sstevel@tonic-gate 					 LDAP_SUCCESS ) {
396*0Sstevel@tonic-gate 					err = -1;
397*0Sstevel@tonic-gate 				}
398*0Sstevel@tonic-gate 				--lc->lconn_refcnt;
399*0Sstevel@tonic-gate 				ld->ld_defconn = savedefconn;
400*0Sstevel@tonic-gate 			}
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 			if ( freepasswd ) {
403*0Sstevel@tonic-gate 				(*ld->ld_rebindproc)( ld, &binddn, &passwd,
404*0Sstevel@tonic-gate 									  &authmethod, 1, ld->ld_rebind_extra_arg );
405*0Sstevel@tonic-gate 			}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 			if ( err != 0 ) {
408*0Sstevel@tonic-gate 				free_connection( ld, lc, 1, 0 );
409*0Sstevel@tonic-gate 				lc = NULL;
410*0Sstevel@tonic-gate 			}
411*0Sstevel@tonic-gate 		}
412*0Sstevel@tonic-gate 	}
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate #ifdef _REENTRANT
415*0Sstevel@tonic-gate 	UNLOCK_LDAP(ld);
416*0Sstevel@tonic-gate #endif
417*0Sstevel@tonic-gate 	return( lc );
418*0Sstevel@tonic-gate }
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate static LDAPConn *
find_connection(LDAP * ld,LDAPServer * srv,int any)422*0Sstevel@tonic-gate find_connection( LDAP *ld, LDAPServer *srv, int any )
423*0Sstevel@tonic-gate /*
424*0Sstevel@tonic-gate  * return an existing connection (if any) to the server srv
425*0Sstevel@tonic-gate  * if "any" is non-zero, check for any server in the "srv" chain
426*0Sstevel@tonic-gate  */
427*0Sstevel@tonic-gate {
428*0Sstevel@tonic-gate 	LDAPConn	*lc;
429*0Sstevel@tonic-gate 	LDAPServer	*ls;
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate #ifdef _REENTRANT
432*0Sstevel@tonic-gate         LOCK_LDAP(ld);
433*0Sstevel@tonic-gate #endif
434*0Sstevel@tonic-gate 	for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
435*0Sstevel@tonic-gate 		for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) {
436*0Sstevel@tonic-gate 			if ( lc->lconn_server->lsrv_host != NULL &&
437*0Sstevel@tonic-gate 			    ls->lsrv_host != NULL && strcasecmp(
438*0Sstevel@tonic-gate 			    ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0
439*0Sstevel@tonic-gate 			    && ls->lsrv_port == lc->lconn_server->lsrv_port ) {
440*0Sstevel@tonic-gate #ifdef _REENTRANT
441*0Sstevel@tonic-gate 				UNLOCK_LDAP(ld);
442*0Sstevel@tonic-gate #endif
443*0Sstevel@tonic-gate 				return( lc );
444*0Sstevel@tonic-gate 			}
445*0Sstevel@tonic-gate 			if ( !any ) {
446*0Sstevel@tonic-gate 				break;
447*0Sstevel@tonic-gate 			}
448*0Sstevel@tonic-gate 		}
449*0Sstevel@tonic-gate 	}
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate #ifdef _REENTRANT
452*0Sstevel@tonic-gate         UNLOCK_LDAP(ld);
453*0Sstevel@tonic-gate #endif
454*0Sstevel@tonic-gate 	return( NULL );
455*0Sstevel@tonic-gate }
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate static void
use_connection(LDAP * ld,LDAPConn * lc)460*0Sstevel@tonic-gate use_connection( LDAP *ld, LDAPConn *lc )
461*0Sstevel@tonic-gate {
462*0Sstevel@tonic-gate 	++lc->lconn_refcnt;
463*0Sstevel@tonic-gate 	lc->lconn_lastused = time( 0 );
464*0Sstevel@tonic-gate }
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate void
free_connection(LDAP * ld,LDAPConn * lc,int force,int unbind)468*0Sstevel@tonic-gate free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
469*0Sstevel@tonic-gate {
470*0Sstevel@tonic-gate 	LDAPConn	*tmplc, *prevlc;
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 211, "free_connection\n"), 0, 0, 0 );
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate 	if ( force || --lc->lconn_refcnt <= 0 ) {
475*0Sstevel@tonic-gate 		if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
476*0Sstevel@tonic-gate 			mark_select_clear( ld, lc->lconn_sb );
477*0Sstevel@tonic-gate 			if ( unbind ) {
478*0Sstevel@tonic-gate 				send_unbind( ld, lc->lconn_sb );
479*0Sstevel@tonic-gate 			}
480*0Sstevel@tonic-gate 			close_ldap_connection( lc->lconn_sb );
481*0Sstevel@tonic-gate 			if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
482*0Sstevel@tonic-gate 				free( lc->lconn_sb->sb_ber.ber_buf );
483*0Sstevel@tonic-gate 				lc->lconn_sb->sb_ber.ber_buf = NULL;
484*0Sstevel@tonic-gate 			}
485*0Sstevel@tonic-gate 		}
486*0Sstevel@tonic-gate 		prevlc = NULL;
487*0Sstevel@tonic-gate 		for ( tmplc = ld->ld_conns; tmplc != NULL;
488*0Sstevel@tonic-gate 		    tmplc = tmplc->lconn_next ) {
489*0Sstevel@tonic-gate 			if ( tmplc == lc ) {
490*0Sstevel@tonic-gate 				if ( prevlc == NULL ) {
491*0Sstevel@tonic-gate 				    ld->ld_conns = tmplc->lconn_next;
492*0Sstevel@tonic-gate 				} else {
493*0Sstevel@tonic-gate 				    prevlc->lconn_next = tmplc->lconn_next;
494*0Sstevel@tonic-gate 				}
495*0Sstevel@tonic-gate 				break;
496*0Sstevel@tonic-gate 			}
497*0Sstevel@tonic-gate 		}
498*0Sstevel@tonic-gate 		free_servers( lc->lconn_server );
499*0Sstevel@tonic-gate 		if ( lc->lconn_krbinstance != NULL ) {
500*0Sstevel@tonic-gate 			free( lc->lconn_krbinstance );
501*0Sstevel@tonic-gate 		}
502*0Sstevel@tonic-gate 		if ( lc->lconn_sb != &ld->ld_sb ) {
503*0Sstevel@tonic-gate 			free( (char *)lc->lconn_sb );
504*0Sstevel@tonic-gate 		}
505*0Sstevel@tonic-gate 		free( lc );
506*0Sstevel@tonic-gate 		Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 212, "free_connection: actually freed\n"),
507*0Sstevel@tonic-gate 		    0, 0, 0 );
508*0Sstevel@tonic-gate 	} else {
509*0Sstevel@tonic-gate 		lc->lconn_lastused = time( 0 );
510*0Sstevel@tonic-gate 		Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 213, "free_connection: refcnt %d\n"),
511*0Sstevel@tonic-gate 		    lc->lconn_refcnt, 0, 0 );
512*0Sstevel@tonic-gate 	}
513*0Sstevel@tonic-gate }
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
517*0Sstevel@tonic-gate void
dump_connection(LDAP * ld,LDAPConn * lconns,int all)518*0Sstevel@tonic-gate dump_connection( LDAP *ld, LDAPConn *lconns, int all )
519*0Sstevel@tonic-gate {
520*0Sstevel@tonic-gate 	LDAPConn	*lc;
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
523*0Sstevel@tonic-gate 	for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
524*0Sstevel@tonic-gate 		if ( lc->lconn_server != NULL ) {
525*0Sstevel@tonic-gate 			fprintf( stderr, "* host: %s  port: %d%s\n",
526*0Sstevel@tonic-gate 			    ( lc->lconn_server->lsrv_host == NULL ) ? "(null)"
527*0Sstevel@tonic-gate 			    : lc->lconn_server->lsrv_host,
528*0Sstevel@tonic-gate 			    lc->lconn_server->lsrv_port, ( lc->lconn_sb ==
529*0Sstevel@tonic-gate 			    &ld->ld_sb ) ? "  (default)" : "" );
530*0Sstevel@tonic-gate 		}
531*0Sstevel@tonic-gate 		fprintf( stderr, "  refcnt: %d  status: %s\n", lc->lconn_refcnt,
532*0Sstevel@tonic-gate 		    ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?
533*0Sstevel@tonic-gate 		    "NeedSocket" : ( lc->lconn_status ==
534*0Sstevel@tonic-gate 		    LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
535*0Sstevel@tonic-gate 		fprintf( stderr, "  last used: %s\n",
536*0Sstevel@tonic-gate 		    ctime( &lc->lconn_lastused ));
537*0Sstevel@tonic-gate 		if ( !all ) {
538*0Sstevel@tonic-gate 			break;
539*0Sstevel@tonic-gate 		}
540*0Sstevel@tonic-gate 	}
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate void
dump_requests_and_responses(LDAP * ld)545*0Sstevel@tonic-gate dump_requests_and_responses( LDAP *ld )
546*0Sstevel@tonic-gate {
547*0Sstevel@tonic-gate 	LDAPRequest	*lr;
548*0Sstevel@tonic-gate 	LDAPMessage	*lm, *l;
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 	fprintf( stderr, "** Outstanding Requests:\n" );
551*0Sstevel@tonic-gate 	if (( lr = ld->ld_requests ) == NULL ) {
552*0Sstevel@tonic-gate 		fprintf( stderr, "   Empty\n" );
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 	for ( ; lr != NULL; lr = lr->lr_next ) {
555*0Sstevel@tonic-gate 	    fprintf( stderr, " * msgid %d,  origid %d, status %s\n",
556*0Sstevel@tonic-gate 		lr->lr_msgid, lr->lr_origid, ( lr->lr_status ==
557*0Sstevel@tonic-gate 		LDAP_REQST_INPROGRESS ) ? "InProgress" :
558*0Sstevel@tonic-gate 		( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
559*0Sstevel@tonic-gate 		( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
560*0Sstevel@tonic-gate 		"Writing" );
561*0Sstevel@tonic-gate 	    fprintf( stderr, "   outstanding referrals %d, parent count %d\n",
562*0Sstevel@tonic-gate 		    lr->lr_outrefcnt, lr->lr_parentcnt );
563*0Sstevel@tonic-gate 	}
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate 	fprintf( stderr, "** Response Queue:\n" );
566*0Sstevel@tonic-gate #ifdef _REENTRANT
567*0Sstevel@tonic-gate         LOCK_RESPONSE(ld);
568*0Sstevel@tonic-gate #endif
569*0Sstevel@tonic-gate 	if (( lm = ld->ld_responses ) == NULLMSG ) {
570*0Sstevel@tonic-gate 		fprintf( stderr, "   Empty\n" );
571*0Sstevel@tonic-gate 	}
572*0Sstevel@tonic-gate 	for ( ; lm != NULLMSG; lm = lm->lm_next ) {
573*0Sstevel@tonic-gate 		fprintf( stderr, " * msgid %d,  type %d\n",
574*0Sstevel@tonic-gate 		    lm->lm_msgid, lm->lm_msgtype );
575*0Sstevel@tonic-gate 		if (( l = lm->lm_chain ) != NULL ) {
576*0Sstevel@tonic-gate 			fprintf( stderr, "   chained responses:\n" );
577*0Sstevel@tonic-gate 			for ( ; l != NULLMSG; l = l->lm_chain ) {
578*0Sstevel@tonic-gate 				fprintf( stderr,
579*0Sstevel@tonic-gate 				    "  * msgid %d,  type %d\n",
580*0Sstevel@tonic-gate 				    l->lm_msgid, l->lm_msgtype );
581*0Sstevel@tonic-gate 			}
582*0Sstevel@tonic-gate 		}
583*0Sstevel@tonic-gate 	}
584*0Sstevel@tonic-gate #ifdef _REENTRANT
585*0Sstevel@tonic-gate 	UNLOCK_RESPONSE(ld);
586*0Sstevel@tonic-gate #endif
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate #endif /* LDAP_DEBUG */
589*0Sstevel@tonic-gate 
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate void
free_request(LDAP * ld,LDAPRequest * lr)592*0Sstevel@tonic-gate free_request( LDAP *ld, LDAPRequest *lr )
593*0Sstevel@tonic-gate {
594*0Sstevel@tonic-gate 	LDAPRequest	*tmplr, *nextlr;
595*0Sstevel@tonic-gate 	int i;
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 214, "free_request (origid %1$d, msgid %2$d)\n"),
598*0Sstevel@tonic-gate 		lr->lr_origid, lr->lr_msgid, 0 );
599*0Sstevel@tonic-gate 
600*0Sstevel@tonic-gate 	if ( lr->lr_parent != NULL ) {
601*0Sstevel@tonic-gate 		--lr->lr_parent->lr_outrefcnt;
602*0Sstevel@tonic-gate 	} else {
603*0Sstevel@tonic-gate 		/* free all referrals (child requests) */
604*0Sstevel@tonic-gate 		for ( tmplr = lr->lr_refnext; tmplr != NULL; tmplr = nextlr ) {
605*0Sstevel@tonic-gate 			nextlr = tmplr->lr_refnext;
606*0Sstevel@tonic-gate 			free_request( ld, tmplr );
607*0Sstevel@tonic-gate 		}
608*0Sstevel@tonic-gate 	}
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	if ( lr->lr_prev == NULL ) {
611*0Sstevel@tonic-gate 		ld->ld_requests = lr->lr_next;
612*0Sstevel@tonic-gate 	} else {
613*0Sstevel@tonic-gate 		lr->lr_prev->lr_next = lr->lr_next;
614*0Sstevel@tonic-gate 	}
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	if ( lr->lr_next != NULL ) {
617*0Sstevel@tonic-gate 		lr->lr_next->lr_prev = lr->lr_prev;
618*0Sstevel@tonic-gate 	}
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate 	if ( lr->lr_ber != NULL ) {
621*0Sstevel@tonic-gate 		ber_free( lr->lr_ber, 1 );
622*0Sstevel@tonic-gate 	}
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 	if ( lr->lr_res_error != NULL ) {
625*0Sstevel@tonic-gate 		free( lr->lr_res_error );
626*0Sstevel@tonic-gate 	}
627*0Sstevel@tonic-gate 
628*0Sstevel@tonic-gate 	if ( lr->lr_res_matched != NULL ) {
629*0Sstevel@tonic-gate 		free( lr->lr_res_matched );
630*0Sstevel@tonic-gate 	}
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 	if ( lr->lr_ref_tofollow != NULL ) {
633*0Sstevel@tonic-gate 		for (i= 0; lr->lr_ref_tofollow[i] != NULL; i++)
634*0Sstevel@tonic-gate 			free(lr->lr_ref_tofollow[i]);
635*0Sstevel@tonic-gate 		free(lr->lr_ref_tofollow);
636*0Sstevel@tonic-gate 	}
637*0Sstevel@tonic-gate 	if ( lr->lr_ref_unfollowed != NULL ) {
638*0Sstevel@tonic-gate 		for (i= 0; lr->lr_ref_unfollowed[i] != NULL; i++)
639*0Sstevel@tonic-gate 			free(lr->lr_ref_unfollowed[i]);
640*0Sstevel@tonic-gate 		free(lr->lr_ref_unfollowed);
641*0Sstevel@tonic-gate 	}
642*0Sstevel@tonic-gate 	if ( lr->lr_ref_followed != NULL ) {
643*0Sstevel@tonic-gate 		for (i= 0; lr->lr_ref_followed[i] != NULL; i++)
644*0Sstevel@tonic-gate 			free(lr->lr_ref_followed[i]);
645*0Sstevel@tonic-gate 		free(lr->lr_ref_followed);
646*0Sstevel@tonic-gate 	}
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 	free( lr );
649*0Sstevel@tonic-gate }
650*0Sstevel@tonic-gate 
651*0Sstevel@tonic-gate 
652*0Sstevel@tonic-gate static void
free_servers(LDAPServer * srvlist)653*0Sstevel@tonic-gate free_servers( LDAPServer *srvlist )
654*0Sstevel@tonic-gate {
655*0Sstevel@tonic-gate     LDAPServer	*nextsrv;
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate     while ( srvlist != NULL ) {
658*0Sstevel@tonic-gate 	nextsrv = srvlist->lsrv_next;
659*0Sstevel@tonic-gate 	if ( srvlist->lsrv_dn != NULL ) {
660*0Sstevel@tonic-gate 		free( srvlist->lsrv_dn );
661*0Sstevel@tonic-gate 	}
662*0Sstevel@tonic-gate 	if ( srvlist->lsrv_host != NULL ) {
663*0Sstevel@tonic-gate 		free( srvlist->lsrv_host );
664*0Sstevel@tonic-gate 	}
665*0Sstevel@tonic-gate 	free( srvlist );
666*0Sstevel@tonic-gate 	srvlist = nextsrv;
667*0Sstevel@tonic-gate     }
668*0Sstevel@tonic-gate }
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate /*
671*0Sstevel@tonic-gate  * nsldapi_connection_lost_nolock() resets "ld" to a non-connected, known
672*0Sstevel@tonic-gate  * state.  It should be called whenever a fatal error occurs on the
673*0Sstevel@tonic-gate  * Sockbuf "sb."  sb == NULL means we don't know specifically where
674*0Sstevel@tonic-gate  * the problem was so we assume all connections are bad.
675*0Sstevel@tonic-gate  */
676*0Sstevel@tonic-gate void
nsldapi_connection_lost_nolock(LDAP * ld,Sockbuf * sb)677*0Sstevel@tonic-gate nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb )
678*0Sstevel@tonic-gate {
679*0Sstevel@tonic-gate 	LDAPRequest	*lr;
680*0Sstevel@tonic-gate 
681*0Sstevel@tonic-gate 	/*
682*0Sstevel@tonic-gate 	 * change status of all pending requests that are associated with "sb
683*0Sstevel@tonic-gate 	 *	to "connection dead."
684*0Sstevel@tonic-gate 	 * also change the connection status to "dead" and remove it from
685*0Sstevel@tonic-gate 	 *	the list of sockets we are interested in.
686*0Sstevel@tonic-gate 	 */
687*0Sstevel@tonic-gate 	for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
688*0Sstevel@tonic-gate 		if ( sb == NULL ||
689*0Sstevel@tonic-gate 		    ( lr->lr_conn != NULL && lr->lr_conn->lconn_sb == sb )) {
690*0Sstevel@tonic-gate 			lr->lr_status = LDAP_REQST_CONNDEAD;
691*0Sstevel@tonic-gate 			if ( lr->lr_conn != NULL ) {
692*0Sstevel@tonic-gate 				lr->lr_conn->lconn_status = LDAP_CONNST_DEAD;
693*0Sstevel@tonic-gate 			}
694*0Sstevel@tonic-gate 		}
695*0Sstevel@tonic-gate 	}
696*0Sstevel@tonic-gate }
697*0Sstevel@tonic-gate 
698*0Sstevel@tonic-gate #ifdef LDAP_DNS
699*0Sstevel@tonic-gate static LDAPServer *
dn2servers(LDAP * ld,char * dn)700*0Sstevel@tonic-gate dn2servers( LDAP *ld, char *dn )	/* dn can also be a domain.... */
701*0Sstevel@tonic-gate {
702*0Sstevel@tonic-gate 	char		*p, *domain, *host, *server_dn, **dxs;
703*0Sstevel@tonic-gate 	int		i, port;
704*0Sstevel@tonic-gate 	LDAPServer	*srvlist, *prevsrv, *srv;
705*0Sstevel@tonic-gate 
706*0Sstevel@tonic-gate 	if (( domain = strrchr( dn, '@' )) != NULL ) {
707*0Sstevel@tonic-gate 		++domain;
708*0Sstevel@tonic-gate 	} else {
709*0Sstevel@tonic-gate 		domain = dn;
710*0Sstevel@tonic-gate 	}
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 	if (( dxs = getdxbyname( domain )) == NULL ) {
713*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
714*0Sstevel@tonic-gate 		return( NULL );
715*0Sstevel@tonic-gate 	}
716*0Sstevel@tonic-gate 
717*0Sstevel@tonic-gate 	srvlist = NULL;
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 	for ( i = 0; dxs[ i ] != NULL; ++i ) {
720*0Sstevel@tonic-gate 		port = LDAP_PORT;
721*0Sstevel@tonic-gate 		server_dn = NULL;
722*0Sstevel@tonic-gate 		if ( strchr( dxs[ i ], ':' ) == NULL ) {
723*0Sstevel@tonic-gate 			host = dxs[ i ];
724*0Sstevel@tonic-gate 		} else if ( strlen( dxs[ i ] ) >= 7 &&
725*0Sstevel@tonic-gate 		    strncmp( dxs[ i ], "ldap://", 7 ) == 0 ) {
726*0Sstevel@tonic-gate 			host = dxs[ i ] + 7;
727*0Sstevel@tonic-gate 			if (( p = strchr( host, ':' )) == NULL ) {
728*0Sstevel@tonic-gate 				p = host;
729*0Sstevel@tonic-gate 			} else {
730*0Sstevel@tonic-gate 				*p++ = '\0';
731*0Sstevel@tonic-gate 				port = atoi( p );
732*0Sstevel@tonic-gate 			}
733*0Sstevel@tonic-gate 			if (( p = strchr( p, '/' )) != NULL ) {
734*0Sstevel@tonic-gate 				server_dn = ++p;
735*0Sstevel@tonic-gate 				if ( *server_dn == '\0' ) {
736*0Sstevel@tonic-gate 					server_dn = NULL;
737*0Sstevel@tonic-gate 				}
738*0Sstevel@tonic-gate 			}
739*0Sstevel@tonic-gate 		} else {
740*0Sstevel@tonic-gate 			host = NULL;
741*0Sstevel@tonic-gate 		}
742*0Sstevel@tonic-gate 
743*0Sstevel@tonic-gate 		if ( host != NULL ) {	/* found a server we can use */
744*0Sstevel@tonic-gate 			if (( srv = (LDAPServer *)calloc( 1,
745*0Sstevel@tonic-gate 			    sizeof( LDAPServer ))) == NULL ) {
746*0Sstevel@tonic-gate 				free_servers( srvlist );
747*0Sstevel@tonic-gate 				srvlist = NULL;
748*0Sstevel@tonic-gate 				break;		/* exit loop & return */
749*0Sstevel@tonic-gate 			}
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate 			/* add to end of list of servers */
752*0Sstevel@tonic-gate 			if ( srvlist == NULL ) {
753*0Sstevel@tonic-gate 				srvlist = srv;
754*0Sstevel@tonic-gate 			} else {
755*0Sstevel@tonic-gate 				prevsrv->lsrv_next = srv;
756*0Sstevel@tonic-gate 			}
757*0Sstevel@tonic-gate 			prevsrv = srv;
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate 			/* copy in info. */
760*0Sstevel@tonic-gate 			if (( srv->lsrv_host = strdup( host )) == NULL ||
761*0Sstevel@tonic-gate 			    ( server_dn != NULL && ( srv->lsrv_dn =
762*0Sstevel@tonic-gate 			    strdup( server_dn )) == NULL )) {
763*0Sstevel@tonic-gate 				free_servers( srvlist );
764*0Sstevel@tonic-gate 				srvlist = NULL;
765*0Sstevel@tonic-gate 				break;		/* exit loop & return */
766*0Sstevel@tonic-gate 			}
767*0Sstevel@tonic-gate 			srv->lsrv_port = port;
768*0Sstevel@tonic-gate 		}
769*0Sstevel@tonic-gate 	}
770*0Sstevel@tonic-gate 
771*0Sstevel@tonic-gate 	ldap_value_free( dxs );
772*0Sstevel@tonic-gate 
773*0Sstevel@tonic-gate 	if ( srvlist == NULL ) {
774*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_SERVER_DOWN;
775*0Sstevel@tonic-gate 	}
776*0Sstevel@tonic-gate 
777*0Sstevel@tonic-gate 	return( srvlist );
778*0Sstevel@tonic-gate }
779*0Sstevel@tonic-gate #endif /* LDAP_DNS */
780