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