1N/A/*
1N/A * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A/*
1N/A * Copyright (c) 1995 Regents of the University of Michigan.
1N/A * All rights reserved.
1N/A *
1N/A * request.c - sending of ldap requests; handling of referrals
1N/A */
1N/A
1N/A#ifndef lint
1N/Astatic char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
1N/A#endif
1N/A
1N/A#include <stdio.h>
1N/A#include <string.h>
1N/A#ifdef MACOS
1N/A#include <stdlib.h>
1N/A#include <time.h>
1N/A#include "macos.h"
1N/A#else /* MACOS */
1N/A#if defined( DOS ) || defined( _WIN32 )
1N/A#include "msdos.h"
1N/A#include <time.h>
1N/A#include <stdlib.h>
1N/A#ifdef PCNFS
1N/A#include <tklib.h>
1N/A#include <tk_errno.h>
1N/A#include <bios.h>
1N/A#endif /* PCNFS */
1N/A#ifdef NCSA
1N/A#include "externs.h"
1N/A#endif /* NCSA */
1N/A#else /* DOS */
1N/A#include <sys/time.h>
1N/A#include <sys/types.h>
1N/A#include <sys/socket.h>
1N/A#include <errno.h>
1N/A#ifdef _AIX
1N/A#include <sys/select.h>
1N/A#endif /* _AIX */
1N/A#include "portable.h"
1N/A#endif /* DOS */
1N/A#endif /* MACOS */
1N/A#ifdef VMS
1N/A#include "ucx_select.h"
1N/A#endif
1N/A#include "lber.h"
1N/A#include "ldap.h"
1N/A#include "ldap-private.h"
1N/A#include "ldap-int.h"
1N/A
1N/A#ifdef USE_SYSCONF
1N/A#include <unistd.h>
1N/A#endif /* USE_SYSCONF */
1N/A
1N/A#ifdef NEEDPROTOS
1N/Astatic LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
1N/Astatic void use_connection( LDAP *ld, LDAPConn *lc );
1N/Astatic void free_servers( LDAPServer *srvlist );
1N/A#else /* NEEDPROTOS */
1N/Astatic LDAPConn *find_connection();
1N/Astatic void use_connection();
1N/Astatic void free_servers();
1N/A#endif /* NEEDPROTOS */
1N/A
1N/A
1N/A#ifdef LDAP_DNS
1N/A#ifdef NEEDPROTOS
1N/Astatic LDAPServer *dn2servers( LDAP *ld, char *dn );
1N/A#else /* NEEDPROTOS */
1N/Astatic LDAPServer *dn2servers();
1N/A#endif /* NEEDPROTOS */
1N/A#endif /* LDAP_DNS */
1N/A
1N/A
1N/ABerElement *
1N/Aalloc_ber_with_options( LDAP *ld )
1N/A{
1N/A BerElement *ber;
1N/A
1N/A if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
1N/A ld->ld_errno = LDAP_NO_MEMORY;
1N/A#ifdef STR_TRANSLATION
1N/A } else {
1N/A set_ber_options( ld, ber );
1N/A#endif /* STR_TRANSLATION */
1N/A }
1N/A
1N/A return( ber );
1N/A}
1N/A
1N/A
1N/Avoid
1N/Aset_ber_options( LDAP *ld, BerElement *ber )
1N/A{
1N/A ber->ber_options = ld->ld_lberoptions;
1N/A#ifdef STR_TRANSLATION
1N/A if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) {
1N/A ber_set_string_translators( ber,
1N/A ld->ld_lber_encode_translate_proc,
1N/A ld->ld_lber_decode_translate_proc );
1N/A }
1N/A#endif /* STR_TRANSLATION */
1N/A}
1N/A
1N/A
1N/Aint
1N/Asend_initial_request( LDAP *ld, unsigned int msgtype, char *dn,
1N/A BerElement *ber )
1N/A{
1N/A LDAPServer *servers;
1N/A int rv;
1N/A
1N/A#ifdef _REENTRANT
1N/A LOCK_LDAP(ld);
1N/A#endif
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 209, "send_initial_request\n"), 0, 0, 0 );
1N/A
1N/A#ifdef LDAP_DNS
1N/A if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
1N/A if (( servers = dn2servers( ld, dn )) == NULL ) {
1N/A ber_free( ber, 1 );
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( -1 );
1N/A }
1N/A
1N/A#ifdef LDAP_DEBUG
1N/A if ( ldap_debug & LDAP_DEBUG_TRACE ) {
1N/A LDAPServer *srv;
1N/A
1N/A for ( srv = servers; srv != NULL;
1N/A srv = srv->lsrv_next ) {
1N/A fprintf( stderr,
1N/A "LDAP server %s: dn %s, port %d\n",
1N/A srv->lsrv_host, ( srv->lsrv_dn == NULL ) ?
1N/A "(default)" : srv->lsrv_dn,
1N/A srv->lsrv_port );
1N/A }
1N/A }
1N/A#endif /* LDAP_DEBUG */
1N/A } else {
1N/A#endif /* LDAP_DNS */
1N/A /*
1N/A * use of DNS is turned off or this is an X.500 DN...
1N/A * use our default connection
1N/A */
1N/A servers = NULL;
1N/A#ifdef LDAP_DNS
1N/A }
1N/A#endif /* LDAP_DNS */
1N/A
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A rv = send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
1N/A NULL, 0 );
1N/A return ( rv );
1N/A}
1N/A
1N/Aint
1N/Asend_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
1N/A *parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
1N/A{
1N/A LDAPRequest *lr;
1N/A int err;
1N/A
1N/A#ifdef _REENTRANT
1N/A LOCK_LDAP(ld);
1N/A#endif
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 210, "send_server_request\n"), 0, 0, 0 );
1N/A
1N/A ld->ld_errno = LDAP_SUCCESS; /* optimistic */
1N/A /* Be optimistic : increment parentreq initially.
1N/A If it fails we must decrement it */
1N/A if (parentreq != NULL){
1N/A parentreq->lr_outrefcnt++;
1N/A }
1N/A
1N/A if ( lc == NULL ) {
1N/A if ( srvlist == NULL ) {
1N/A if (ld->ld_defconn == NULL){ /* Not connected yet on the default connection, ie init was called not open */
1N/A if ((err = open_default_ldap_connection(ld)) != LDAP_SUCCESS){
1N/A ld->ld_errno = err;
1N/A ber_free(ber, 1);
1N/A if (parentreq != NULL){
1N/A parentreq->lr_outrefcnt--;
1N/A }
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( -1 );
1N/A }
1N/A }
1N/A
1N/A lc = ld->ld_defconn;
1N/A } else {
1N/A if (( lc = find_connection( ld, srvlist, 1 )) ==
1N/A NULL ) {
1N/A lc = new_connection( ld, &srvlist, 0, 1, bind );
1N/A }
1N/A free_servers( srvlist );
1N/A }
1N/A }
1N/A
1N/A if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
1N/A ber_free( ber, 1 );
1N/A if ( ld->ld_errno == LDAP_SUCCESS ) {
1N/A ld->ld_errno = LDAP_SERVER_DOWN;
1N/A }
1N/A if (parentreq != NULL){
1N/A parentreq->lr_outrefcnt--;
1N/A }
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( -1 );
1N/A }
1N/A
1N/A use_connection( ld, lc );
1N/A if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
1N/A NULL ) {
1N/A ld->ld_errno = LDAP_NO_MEMORY;
1N/A free_connection( ld, lc, 0, 0 );
1N/A ber_free( ber, 1 );
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( -1 );
1N/A }
1N/A lr->lr_msgid = msgid;
1N/A lr->lr_status = LDAP_REQST_INPROGRESS;
1N/A lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */
1N/A lr->lr_ber = ber;
1N/A lr->lr_conn = lc;
1N/A if ( parentreq != NULL ) { /* sub-request */
1N/A/* ++parentreq->lr_outrefcnt; */
1N/A lr->lr_origid = parentreq->lr_origid;
1N/A lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
1N/A lr->lr_parent = parentreq;
1N/A lr->lr_refnext = parentreq->lr_refnext;
1N/A parentreq->lr_refnext = lr;
1N/A } else { /* original request */
1N/A lr->lr_origid = lr->lr_msgid;
1N/A }
1N/A
1N/A if (( lr->lr_next = ld->ld_requests ) != NULL ) {
1N/A lr->lr_next->lr_prev = lr;
1N/A }
1N/A ld->ld_requests = lr;
1N/A lr->lr_prev = NULL;
1N/A
1N/A if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
1N/A#ifdef notyet
1N/A extern int errno;
1N/A
1N/A if ( errno == EWOULDBLOCK ) {
1N/A /* need to continue write later */
1N/A lr->lr_status = LDAP_REQST_WRITING;
1N/A mark_select_write( ld, lc->lconn_sb );
1N/A } else {
1N/A#else /* notyet */
1N/A ld->ld_errno = LDAP_SERVER_DOWN;
1N/A free_request( ld, lr );
1N/A free_connection( ld, lc, 0, 0 );
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( -1 );
1N/A#endif /* notyet */
1N/A#ifdef notyet
1N/A }
1N/A#endif /* notyet */
1N/A } else {
1N/A if ( parentreq == NULL ) {
1N/A ber->ber_end = ber->ber_ptr;
1N/A ber->ber_ptr = ber->ber_buf;
1N/A }
1N/A
1N/A /* sent -- waiting for a response */
1N/A mark_select_read( ld, lc->lconn_sb );
1N/A }
1N/A
1N/A ld->ld_errno = LDAP_SUCCESS;
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( msgid );
1N/A}
1N/A
1N/A
1N/ALDAPConn *
1N/Anew_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
1N/A int connect, int bind )
1N/A{
1N/A LDAPConn *lc;
1N/A LDAPServer *prevsrv, *srv;
1N/A Sockbuf *sb;
1N/A
1N/A /*
1N/A * make a new LDAP server connection
1N/A * XXX open connection synchronously for now
1N/A */
1N/A if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
1N/A ( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
1N/A == NULL )) {
1N/A if ( lc != NULL ) {
1N/A free( (char *)lc );
1N/A }
1N/A ld->ld_errno = LDAP_NO_MEMORY;
1N/A return( NULL );
1N/A }
1N/A
1N/A#ifdef _REENTRANT
1N/A LOCK_LDAP(ld);
1N/A#endif
1N/A lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
1N/A
1N/A if ( connect ) {
1N/A prevsrv = NULL;
1N/A
1N/A for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) {
1N/A if ( open_ldap_connection( ld, lc->lconn_sb,
1N/A srv->lsrv_host, srv->lsrv_port,
1N/A &lc->lconn_krbinstance, 0 ) != -1 ) {
1N/A break;
1N/A }
1N/A prevsrv = srv;
1N/A }
1N/A
1N/A if ( srv == NULL ) {
1N/A if ( !use_ldsb ) {
1N/A free( (char *)lc->lconn_sb );
1N/A }
1N/A free( (char *)lc );
1N/A ld->ld_errno = LDAP_SERVER_DOWN;
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( NULL );
1N/A }
1N/A
1N/A if ( prevsrv == NULL ) {
1N/A *srvlistp = srv->lsrv_next;
1N/A } else {
1N/A prevsrv->lsrv_next = srv->lsrv_next;
1N/A }
1N/A lc->lconn_server = srv;
1N/A }
1N/A
1N/A lc->lconn_status = LDAP_CONNST_CONNECTED;
1N/A lc->lconn_next = ld->ld_conns;
1N/A ld->ld_conns = lc;
1N/A
1N/A /*
1N/A * XXX for now, we always do a synchronous bind. This will have
1N/A * to change in the long run...
1N/A */
1N/A if ( bind ) {
1N/A int err, freepasswd, authmethod;
1N/A char *binddn, *passwd;
1N/A LDAPConn *savedefconn;
1N/A
1N/A freepasswd = err = 0;
1N/A
1N/A if ( ld->ld_version == LDAP_VERSION3 && ld->ld_rebindproc == NULL){
1N/A /* Nothing to do */
1N/A Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1280, "new_connection: bind no needed with ldapv3\n"), 0,0,0);
1N/A } else {
1N/A if ( ld->ld_rebindproc == NULL ) {
1N/A binddn = passwd = "";
1N/A authmethod = LDAP_AUTH_SIMPLE;
1N/A } else {
1N/A if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd,
1N/A &authmethod, 0, ld->ld_rebind_extra_arg )) == LDAP_SUCCESS ) {
1N/A freepasswd = 1;
1N/A } else {
1N/A ld->ld_errno = err;
1N/A err = -1;
1N/A }
1N/A }
1N/A
1N/A if ( err == 0 ) {
1N/A savedefconn = ld->ld_defconn;
1N/A ld->ld_defconn = lc;
1N/A ++lc->lconn_refcnt; /* avoid premature free */
1N/A
1N/A if ( ldap_bind_s( ld, binddn, passwd, authmethod ) !=
1N/A LDAP_SUCCESS ) {
1N/A err = -1;
1N/A }
1N/A --lc->lconn_refcnt;
1N/A ld->ld_defconn = savedefconn;
1N/A }
1N/A
1N/A if ( freepasswd ) {
1N/A (*ld->ld_rebindproc)( ld, &binddn, &passwd,
1N/A &authmethod, 1, ld->ld_rebind_extra_arg );
1N/A }
1N/A
1N/A if ( err != 0 ) {
1N/A free_connection( ld, lc, 1, 0 );
1N/A lc = NULL;
1N/A }
1N/A }
1N/A }
1N/A
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( lc );
1N/A}
1N/A
1N/A
1N/Astatic LDAPConn *
1N/Afind_connection( LDAP *ld, LDAPServer *srv, int any )
1N/A/*
1N/A * return an existing connection (if any) to the server srv
1N/A * if "any" is non-zero, check for any server in the "srv" chain
1N/A */
1N/A{
1N/A LDAPConn *lc;
1N/A LDAPServer *ls;
1N/A
1N/A#ifdef _REENTRANT
1N/A LOCK_LDAP(ld);
1N/A#endif
1N/A for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
1N/A for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) {
1N/A if ( lc->lconn_server->lsrv_host != NULL &&
1N/A ls->lsrv_host != NULL && strcasecmp(
1N/A ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0
1N/A && ls->lsrv_port == lc->lconn_server->lsrv_port ) {
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( lc );
1N/A }
1N/A if ( !any ) {
1N/A break;
1N/A }
1N/A }
1N/A }
1N/A
1N/A#ifdef _REENTRANT
1N/A UNLOCK_LDAP(ld);
1N/A#endif
1N/A return( NULL );
1N/A}
1N/A
1N/A
1N/A
1N/Astatic void
1N/Ause_connection( LDAP *ld, LDAPConn *lc )
1N/A{
1N/A ++lc->lconn_refcnt;
1N/A lc->lconn_lastused = time( 0 );
1N/A}
1N/A
1N/A
1N/Avoid
1N/Afree_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
1N/A{
1N/A LDAPConn *tmplc, *prevlc;
1N/A
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 211, "free_connection\n"), 0, 0, 0 );
1N/A
1N/A if ( force || --lc->lconn_refcnt <= 0 ) {
1N/A if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
1N/A mark_select_clear( ld, lc->lconn_sb );
1N/A if ( unbind ) {
1N/A send_unbind( ld, lc->lconn_sb );
1N/A }
1N/A close_ldap_connection( lc->lconn_sb );
1N/A if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
1N/A free( lc->lconn_sb->sb_ber.ber_buf );
1N/A lc->lconn_sb->sb_ber.ber_buf = NULL;
1N/A }
1N/A }
1N/A prevlc = NULL;
1N/A for ( tmplc = ld->ld_conns; tmplc != NULL;
1N/A tmplc = tmplc->lconn_next ) {
1N/A if ( tmplc == lc ) {
1N/A if ( prevlc == NULL ) {
1N/A ld->ld_conns = tmplc->lconn_next;
1N/A } else {
1N/A prevlc->lconn_next = tmplc->lconn_next;
1N/A }
1N/A break;
1N/A }
1N/A }
1N/A free_servers( lc->lconn_server );
1N/A if ( lc->lconn_krbinstance != NULL ) {
1N/A free( lc->lconn_krbinstance );
1N/A }
1N/A if ( lc->lconn_sb != &ld->ld_sb ) {
1N/A free( (char *)lc->lconn_sb );
1N/A }
1N/A free( lc );
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 212, "free_connection: actually freed\n"),
1N/A 0, 0, 0 );
1N/A } else {
1N/A lc->lconn_lastused = time( 0 );
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 213, "free_connection: refcnt %d\n"),
1N/A lc->lconn_refcnt, 0, 0 );
1N/A }
1N/A}
1N/A
1N/A
1N/A#ifdef LDAP_DEBUG
1N/Avoid
1N/Adump_connection( LDAP *ld, LDAPConn *lconns, int all )
1N/A{
1N/A LDAPConn *lc;
1N/A
1N/A fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
1N/A for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
1N/A if ( lc->lconn_server != NULL ) {
1N/A fprintf( stderr, "* host: %s port: %d%s\n",
1N/A ( lc->lconn_server->lsrv_host == NULL ) ? "(null)"
1N/A : lc->lconn_server->lsrv_host,
1N/A lc->lconn_server->lsrv_port, ( lc->lconn_sb ==
1N/A &ld->ld_sb ) ? " (default)" : "" );
1N/A }
1N/A fprintf( stderr, " refcnt: %d status: %s\n", lc->lconn_refcnt,
1N/A ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?
1N/A "NeedSocket" : ( lc->lconn_status ==
1N/A LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
1N/A fprintf( stderr, " last used: %s\n",
1N/A ctime( &lc->lconn_lastused ));
1N/A if ( !all ) {
1N/A break;
1N/A }
1N/A }
1N/A}
1N/A
1N/A
1N/Avoid
1N/Adump_requests_and_responses( LDAP *ld )
1N/A{
1N/A LDAPRequest *lr;
1N/A LDAPMessage *lm, *l;
1N/A
1N/A fprintf( stderr, "** Outstanding Requests:\n" );
1N/A if (( lr = ld->ld_requests ) == NULL ) {
1N/A fprintf( stderr, " Empty\n" );
1N/A }
1N/A for ( ; lr != NULL; lr = lr->lr_next ) {
1N/A fprintf( stderr, " * msgid %d, origid %d, status %s\n",
1N/A lr->lr_msgid, lr->lr_origid, ( lr->lr_status ==
1N/A LDAP_REQST_INPROGRESS ) ? "InProgress" :
1N/A ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
1N/A ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
1N/A "Writing" );
1N/A fprintf( stderr, " outstanding referrals %d, parent count %d\n",
1N/A lr->lr_outrefcnt, lr->lr_parentcnt );
1N/A }
1N/A
1N/A fprintf( stderr, "** Response Queue:\n" );
1N/A#ifdef _REENTRANT
1N/A LOCK_RESPONSE(ld);
1N/A#endif
1N/A if (( lm = ld->ld_responses ) == NULLMSG ) {
1N/A fprintf( stderr, " Empty\n" );
1N/A }
1N/A for ( ; lm != NULLMSG; lm = lm->lm_next ) {
1N/A fprintf( stderr, " * msgid %d, type %d\n",
1N/A lm->lm_msgid, lm->lm_msgtype );
1N/A if (( l = lm->lm_chain ) != NULL ) {
1N/A fprintf( stderr, " chained responses:\n" );
1N/A for ( ; l != NULLMSG; l = l->lm_chain ) {
1N/A fprintf( stderr,
1N/A " * msgid %d, type %d\n",
1N/A l->lm_msgid, l->lm_msgtype );
1N/A }
1N/A }
1N/A }
1N/A#ifdef _REENTRANT
1N/A UNLOCK_RESPONSE(ld);
1N/A#endif
1N/A}
1N/A#endif /* LDAP_DEBUG */
1N/A
1N/A
1N/Avoid
1N/Afree_request( LDAP *ld, LDAPRequest *lr )
1N/A{
1N/A LDAPRequest *tmplr, *nextlr;
1N/A int i;
1N/A
1N/A Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 214, "free_request (origid %1$d, msgid %2$d)\n"),
1N/A lr->lr_origid, lr->lr_msgid, 0 );
1N/A
1N/A if ( lr->lr_parent != NULL ) {
1N/A --lr->lr_parent->lr_outrefcnt;
1N/A } else {
1N/A /* free all referrals (child requests) */
1N/A for ( tmplr = lr->lr_refnext; tmplr != NULL; tmplr = nextlr ) {
1N/A nextlr = tmplr->lr_refnext;
1N/A free_request( ld, tmplr );
1N/A }
1N/A }
1N/A
1N/A if ( lr->lr_prev == NULL ) {
1N/A ld->ld_requests = lr->lr_next;
1N/A } else {
1N/A lr->lr_prev->lr_next = lr->lr_next;
1N/A }
1N/A
1N/A if ( lr->lr_next != NULL ) {
1N/A lr->lr_next->lr_prev = lr->lr_prev;
1N/A }
1N/A
1N/A if ( lr->lr_ber != NULL ) {
1N/A ber_free( lr->lr_ber, 1 );
1N/A }
1N/A
1N/A if ( lr->lr_res_error != NULL ) {
1N/A free( lr->lr_res_error );
1N/A }
1N/A
1N/A if ( lr->lr_res_matched != NULL ) {
1N/A free( lr->lr_res_matched );
1N/A }
1N/A
1N/A if ( lr->lr_ref_tofollow != NULL ) {
1N/A for (i= 0; lr->lr_ref_tofollow[i] != NULL; i++)
1N/A free(lr->lr_ref_tofollow[i]);
1N/A free(lr->lr_ref_tofollow);
1N/A }
1N/A if ( lr->lr_ref_unfollowed != NULL ) {
1N/A for (i= 0; lr->lr_ref_unfollowed[i] != NULL; i++)
1N/A free(lr->lr_ref_unfollowed[i]);
1N/A free(lr->lr_ref_unfollowed);
1N/A }
1N/A if ( lr->lr_ref_followed != NULL ) {
1N/A for (i= 0; lr->lr_ref_followed[i] != NULL; i++)
1N/A free(lr->lr_ref_followed[i]);
1N/A free(lr->lr_ref_followed);
1N/A }
1N/A
1N/A free( lr );
1N/A}
1N/A
1N/A
1N/Astatic void
1N/Afree_servers( LDAPServer *srvlist )
1N/A{
1N/A LDAPServer *nextsrv;
1N/A
1N/A while ( srvlist != NULL ) {
1N/A nextsrv = srvlist->lsrv_next;
1N/A if ( srvlist->lsrv_dn != NULL ) {
1N/A free( srvlist->lsrv_dn );
1N/A }
1N/A if ( srvlist->lsrv_host != NULL ) {
1N/A free( srvlist->lsrv_host );
1N/A }
1N/A free( srvlist );
1N/A srvlist = nextsrv;
1N/A }
1N/A}
1N/A
1N/A/*
1N/A * nsldapi_connection_lost_nolock() resets "ld" to a non-connected, known
1N/A * state. It should be called whenever a fatal error occurs on the
1N/A * Sockbuf "sb." sb == NULL means we don't know specifically where
1N/A * the problem was so we assume all connections are bad.
1N/A */
1N/Avoid
1N/Ansldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb )
1N/A{
1N/A LDAPRequest *lr;
1N/A
1N/A /*
1N/A * change status of all pending requests that are associated with "sb
1N/A * to "connection dead."
1N/A * also change the connection status to "dead" and remove it from
1N/A * the list of sockets we are interested in.
1N/A */
1N/A for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
1N/A if ( sb == NULL ||
1N/A ( lr->lr_conn != NULL && lr->lr_conn->lconn_sb == sb )) {
1N/A lr->lr_status = LDAP_REQST_CONNDEAD;
1N/A if ( lr->lr_conn != NULL ) {
1N/A lr->lr_conn->lconn_status = LDAP_CONNST_DEAD;
1N/A }
1N/A }
1N/A }
1N/A}
1N/A
1N/A#ifdef LDAP_DNS
1N/Astatic LDAPServer *
1N/Adn2servers( LDAP *ld, char *dn ) /* dn can also be a domain.... */
1N/A{
1N/A char *p, *domain, *host, *server_dn, **dxs;
1N/A int i, port;
1N/A LDAPServer *srvlist, *prevsrv, *srv;
1N/A
1N/A if (( domain = strrchr( dn, '@' )) != NULL ) {
1N/A ++domain;
1N/A } else {
1N/A domain = dn;
1N/A }
1N/A
1N/A if (( dxs = getdxbyname( domain )) == NULL ) {
1N/A ld->ld_errno = LDAP_NO_MEMORY;
1N/A return( NULL );
1N/A }
1N/A
1N/A srvlist = NULL;
1N/A
1N/A for ( i = 0; dxs[ i ] != NULL; ++i ) {
1N/A port = LDAP_PORT;
1N/A server_dn = NULL;
1N/A if ( strchr( dxs[ i ], ':' ) == NULL ) {
1N/A host = dxs[ i ];
1N/A } else if ( strlen( dxs[ i ] ) >= 7 &&
1N/A strncmp( dxs[ i ], "ldap://", 7 ) == 0 ) {
1N/A host = dxs[ i ] + 7;
1N/A if (( p = strchr( host, ':' )) == NULL ) {
1N/A p = host;
1N/A } else {
1N/A *p++ = '\0';
1N/A port = atoi( p );
1N/A }
1N/A if (( p = strchr( p, '/' )) != NULL ) {
1N/A server_dn = ++p;
1N/A if ( *server_dn == '\0' ) {
1N/A server_dn = NULL;
1N/A }
1N/A }
1N/A } else {
1N/A host = NULL;
1N/A }
1N/A
1N/A if ( host != NULL ) { /* found a server we can use */
1N/A if (( srv = (LDAPServer *)calloc( 1,
1N/A sizeof( LDAPServer ))) == NULL ) {
1N/A free_servers( srvlist );
1N/A srvlist = NULL;
1N/A break; /* exit loop & return */
1N/A }
1N/A
1N/A /* add to end of list of servers */
1N/A if ( srvlist == NULL ) {
1N/A srvlist = srv;
1N/A } else {
1N/A prevsrv->lsrv_next = srv;
1N/A }
1N/A prevsrv = srv;
1N/A
1N/A /* copy in info. */
1N/A if (( srv->lsrv_host = strdup( host )) == NULL ||
1N/A ( server_dn != NULL && ( srv->lsrv_dn =
1N/A strdup( server_dn )) == NULL )) {
1N/A free_servers( srvlist );
1N/A srvlist = NULL;
1N/A break; /* exit loop & return */
1N/A }
1N/A srv->lsrv_port = port;
1N/A }
1N/A }
1N/A
1N/A ldap_value_free( dxs );
1N/A
1N/A if ( srvlist == NULL ) {
1N/A ld->ld_errno = LDAP_SERVER_DOWN;
1N/A }
1N/A
1N/A return( srvlist );
1N/A}
1N/A#endif /* LDAP_DNS */