]> git.sur5r.net Git - openldap/commitdiff
LDAP_OPT_NETWORK_TIMEOUT feature (ITS#239) from Lars Uffmann.
authorKurt Zeilenga <kurt@openldap.org>
Tue, 3 Aug 1999 19:27:22 +0000 (19:27 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Tue, 3 Aug 1999 19:27:22 +0000 (19:27 +0000)
Needs a bit more work.
- global net/api timeouts are not inherited on session creation.
- need configure check for inet_aton() (coming soon)
- ioctl/fcntl portability issues (should share implementation
with lber routines)

include/ldap.h
libraries/libldap/init.c
libraries/libldap/ldap-int.h
libraries/libldap/open.c
libraries/libldap/options.c
libraries/libldap/os-ip.c
libraries/libldap/unbind.c

index 70ab7318fec62587cd7cd8b5f25de8e55f50a40b..460237727020d4ba96c8314a10dc519c334301b1 100644 (file)
@@ -112,6 +112,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_TIMEOUT                       0x5002  /* default timeout */
 #define LDAP_OPT_REFHOPLIMIT           0x5003  /* ref hop limit */
 #define LDAP_OPT_MATCHED_DN                    0x5004  /* should have been in draft */
+#define LDAP_OPT_NETWORK_TIMEOUT        0x5005  /* socket level timeout */
 
 /* TLS options */
 #define LDAP_OPT_X_TLS_CACERTFILE      0x6001
index 5906bf78ae2f0a4018da9badaad54404f40e71f0..c49b372ae93c2818f48315a9c0f8cdaf051c07de 100644 (file)
@@ -315,12 +315,15 @@ void ldap_int_initialize( void )
        if ( ldap_int_tblsize == 0 )
                ldap_int_ip_init();
 
+       gopts.ldo_debug = 0;
+
        gopts.ldo_version =     LDAP_VERSION2;
        gopts.ldo_deref =       LDAP_DEREF_NEVER;
        gopts.ldo_timelimit = LDAP_NO_LIMIT;
        gopts.ldo_sizelimit = LDAP_NO_LIMIT;
 
-       gopts.ldo_debug = 0;
+       gopts.ldo_tm_api = (struct timeval *)NULL;
+       gopts.ldo_tm_net = (struct timeval *)NULL;
 
        gopts.ldo_defhost = LDAP_STRDUP("localhost");
        gopts.ldo_defport = LDAP_PORT;
index 6b1ca1a027eca2663cc97c0e3fb4b78251d82019..e9146db127075b985e0816da0e673d53345672a7 100644 (file)
@@ -90,6 +90,9 @@ struct ldapoptions {
 #define LDAP_VALID_SESSION     0x2
 
        int             ldo_debug;
+       /* per API call timeout */
+       struct timeval          *ldo_tm_api;
+       struct timeval          *ldo_tm_net;
 
        ber_int_t               ldo_version;    /* version to connect at */
        ber_int_t               ldo_deref;
@@ -119,6 +122,7 @@ struct ldapoptions {
        LDAP_BOOLEANS ldo_booleans;     /* boolean options */
 };
 
+
 /*
  * structure for tracking LDAP server host, ports, DNs, etc.
  */
@@ -353,9 +357,10 @@ int open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport,
  * in os-ip.c
  */
 extern int ldap_int_tblsize;
+int ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm );
+int ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host,
+       unsigned long address, int port, int async );
 
-int ldap_connect_to_host( Sockbuf *sb, const char *host, unsigned long address, int port,
-       int async );
 void ldap_close_connection( Sockbuf *sb );
 
 #ifdef HAVE_KERBEROS
index 419b4277e0cca5b215c193fe9fd04a0d034cfdee..93019b0915c52b2e55bfb5d9d73f9035cbf2fc81 100644 (file)
@@ -236,13 +236,13 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport,
                            port = defport;   
                        }
 
-                       if (( rc = ldap_connect_to_host( sb, curhost, 0L,
+                       if (( rc = ldap_connect_to_host( ld, sb, curhost, 0L,
                            port, async )) != -1 ) {
                                break;
                        }
                }
        } else {
-               rc = ldap_connect_to_host( sb, NULL, htonl( INADDR_LOOPBACK ),
+               rc = ldap_connect_to_host( ld, sb, 0, htonl( INADDR_LOOPBACK ),
                    defport, async );
        }
 
index b3dd1b4d58f3a9b073949b0c3405d4348be815aa..c66ac0ab1fe74bbeee600d03b6d9025c66ea195d 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <ac/socket.h>
 #include <ac/string.h>
+#include <ac/time.h>
 
 #include "ldap-int.h"
 
@@ -155,6 +156,22 @@ ldap_get_option(
                * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
                return LDAP_OPT_SUCCESS;
 
+       case LDAP_OPT_TIMEOUT:
+               /* the caller has to free outvalue ! */
+               if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
+               {
+                       return LDAP_OPT_ERROR;
+               }
+               return LDAP_OPT_SUCCESS;
+               
+       case LDAP_OPT_NETWORK_TIMEOUT:
+               /* the caller has to free outvalue ! */
+               if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
+               {
+                       return LDAP_OPT_ERROR;
+               }
+               return LDAP_OPT_SUCCESS;
+
        case LDAP_OPT_DEREF:
                * (int *) outvalue = lo->ldo_deref;
                return LDAP_OPT_SUCCESS;
@@ -322,38 +339,8 @@ ldap_set_option(
                return LDAP_OPT_SUCCESS;
        }
 
-       if(invalue == NULL) {
-               /* no place to set from */
-               return LDAP_OPT_ERROR;
-       }
-
-       switch(option) {
-       case LDAP_OPT_API_INFO:
-       case LDAP_OPT_DESC:
-               /* READ ONLY */
-               break;
-
-       case LDAP_OPT_DEREF:
-               lo->ldo_deref = * (const int *) invalue;
-               return LDAP_OPT_SUCCESS;
-
-       case LDAP_OPT_SIZELIMIT:
-               lo->ldo_sizelimit = * (const int *) invalue;
-               return LDAP_OPT_SUCCESS;
-
-       case LDAP_OPT_TIMELIMIT:
-               lo->ldo_timelimit = * (const int *) invalue;
-               return LDAP_OPT_SUCCESS;
-
-       case LDAP_OPT_PROTOCOL_VERSION: {
-                       int vers = * (const int *) invalue;
-                       if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
-                               /* not supported */
-                               break;
-                       }
-                       ld->ld_version = vers;
-               } return LDAP_OPT_SUCCESS;
-
+       /* options which can withstand invalue == NULL */
+       switch ( option ) {
        case LDAP_OPT_SERVER_CONTROLS: {
                        LDAPControl *const *controls =
                                (LDAPControl *const *) invalue;
@@ -392,6 +379,70 @@ ldap_set_option(
                        }
                } return LDAP_OPT_SUCCESS;
 
+       case LDAP_OPT_TIMEOUT: {
+                       const struct timeval *tv = 
+                               (struct timeval *) invalue;
+
+                       if ( lo->ldo_tm_api != NULL ) {
+                               LDAP_FREE( lo->ldo_tm_api );
+                               lo->ldo_tm_api = NULL;
+                       }
+
+                       if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
+                               return LDAP_OPT_ERROR;
+                       }
+               } return LDAP_OPT_SUCCESS;
+
+       case LDAP_OPT_NETWORK_TIMEOUT: {
+                       const struct timeval *tv = 
+                               (struct timeval *) invalue;
+
+                       if ( lo->ldo_tm_net != NULL ) {
+                               LDAP_FREE( lo->ldo_tm_net );
+                               lo->ldo_tm_net = NULL;
+                       }
+
+                       if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
+                               return LDAP_OPT_ERROR;
+                       }
+               } return LDAP_OPT_SUCCESS;
+       }
+
+       if(invalue == NULL) {
+               /* no place to set from */
+               return LDAP_OPT_ERROR;
+       }
+
+       /* options which cannot withstand invalue == NULL */
+
+       switch(option) {
+       case LDAP_OPT_API_INFO:
+       case LDAP_OPT_DESC:
+               /* READ ONLY */
+               break;
+
+       case LDAP_OPT_DEREF:
+               lo->ldo_deref = * (const int *) invalue;
+               return LDAP_OPT_SUCCESS;
+
+       case LDAP_OPT_SIZELIMIT:
+               lo->ldo_sizelimit = * (const int *) invalue;
+               return LDAP_OPT_SUCCESS;
+
+       case LDAP_OPT_TIMELIMIT:
+               lo->ldo_timelimit = * (const int *) invalue;
+               return LDAP_OPT_SUCCESS;
+
+       case LDAP_OPT_PROTOCOL_VERSION: {
+                       int vers = * (const int *) invalue;
+                       if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
+                               /* not supported */
+                               break;
+                       }
+                       ld->ld_version = vers;
+               } return LDAP_OPT_SUCCESS;
+
+
        case LDAP_OPT_HOST_NAME: {
                        const char *host = (const char *) invalue;
 
index 729c5d7902a4502c3e77de0dea9dbaf60d1d5c9a..140f333e749b15442141ad184fbc26bd74ee15f7 100644 (file)
 #include <io.h>
 #endif /* HAVE_IO_H */
 
+#if defined( HAVE_FCNTL_H )
+#include <fcntl.h>
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+#endif /* HAVE_FCNTL_H */
+
 #if defined( HAVE_SYS_FILIO_H )
 #include <sys/filio.h>
 #elif defined( HAVE_SYS_IOCTL_H )
 
 int ldap_int_tblsize = 0;
 
-
-int
-ldap_connect_to_host( Sockbuf *sb, const char *host, unsigned long address,
-       int port, int async )
 /*
- * if host == NULL, connect using address
- * "address" and "port" must be in network byte order
- * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
- * async is only used ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS (non-0 means don't wait for connect)
- * XXX async is not used yet!
+ * nonblock connect code
+ * written by Lars Uffmann, <lars.uffmann@mediaway.net>.
+ *
+ * Copyright 1999, Lars Uffmann, All rights reserved.
+ * This software is not subject to any license of my employer
+ * mediaWays GmbH.
+ *
+ * OpenLDAP COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ *
+ * Read about the rationale in ldap_connect_timeout: 
+ * ftp://koobera.math.uic.edu/www/docs/connect.html.
  */
+
+#define osip_debug(ld,fmt,arg1,arg2,arg3) \
+do { \
+       ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \
+} while(0)
+
+static void
+ldap_pvt_set_errno(int err)
 {
-       int                     rc, i;
-       ber_socket_t s = AC_SOCKET_INVALID;
-       int                     connected, use_hp;
-       struct sockaddr_in      sin;
-       struct hostent          *hp = NULL;
+       errno = err;
+}
+
+int
+ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src )
+{
+       struct timeval *new;
+
+       assert( dest != NULL );
+
+       if (src == NULL) {
+               *dest = NULL;
+               return 0;
+       }
+
+       new = (struct timeval *) malloc(sizeof(struct timeval));
+
+       if( new == NULL ) {
+               *dest = NULL;
+               return 1;
+       }
+
+       SAFEMEMCPY( (char *) new, (char *) src, sizeof(struct timeval));
+
+       *dest = new;
+       return 0;
+}
+
+static int
+ldap_pvt_ndelay_on(LDAP *ld, int fd)
+{
+       osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0);
 #ifdef notyet
-       ioctl_t                 status; /* for ioctl call */
-#endif /* notyet */
-   
-       /* buffers for ldap_pvt_gethostbyname_a */
-       struct hostent          he_buf;
-       int                     local_h_errno;
-       char                    *ha_buf=NULL;
-#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
+/* #if defined( HAVE_FCNTL_H ) */
+       return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
+#else
+{
+       ioctl_t status = 1;
+       return ioctl( fd, FIONBIO, (caddr_t)&status );
+}
+#endif
+       return 0;
+}
    
-       Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
-           ( host == NULL ) ? "(by address)" : host, (int) ntohs( (short) port ), 0 );
-
-       connected = use_hp = 0;
-
-       if ( host != NULL ) {
-           address = inet_addr( host );
-           /* This was just a test for -1 until OSF1 let inet_addr return
-              unsigned int, which is narrower than 'unsigned long address' */
-           if ( address == 0xffffffff || address == (unsigned long) -1 ) {
-               if ( ( ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
-                       &hp, &local_h_errno) < 0) || (hp==NULL))
-               {
-#ifdef HAVE_WINSOCK
-                       errno = WSAGetLastError();
+static int
+ldap_pvt_ndelay_off(LDAP *ld, int fd)
+{
+       osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0);
+#ifdef notyet
+/* #if defined( HAVE_FCNTL_H ) */
+       return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
 #else
-                       errno = EHOSTUNREACH;   /* not exactly right, but... */
+{
+       ioctl_t status = 0;
+       return ioctl( fd, FIONBIO, (caddr_t)&status );
+}
 #endif
-                       DO_RETURN( -1 );
-               }
-               use_hp = 1;
-           }
-       }
+}
+
+static ber_socket_t
+ldap_pvt_socket(LDAP *ld)
+{
+       ber_socket_t s = socket(AF_INET, SOCK_STREAM, 0);
+       osip_debug(ld, "ldap_new_socket: %d\n",s,0,0);
+       return ( s );
+}
+
+static int
+ldap_pvt_close_socket(LDAP *ld, int s)
+{
+       osip_debug(ld, "ldap_close_socket: %d\n",s,0,0);
+       return tcp_close(s);
+}
+
+static int
+ldap_pvt_prepare_socket(LDAP *ld, int fd)
+{
+       osip_debug(ld, "ldap_prepare_socket: %d\n",fd,0,0);
 
-       rc = -1;
-       for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
-               if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
-                       DO_RETURN( -1 );
-               }
 #ifdef TCP_NODELAY
-               {
-                       int tmp = 1;
-                       if( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
-                               (char *) &tmp, sizeof(tmp) ) == -1 )
-                       {
-                               Debug( LDAP_DEBUG_ANY,
-                                       "setsockopt(TCP_NODELAY failed on %d\n",
-                                       s, 0, 0 );
-                       }
-               }
+{
+       int dummy = 1;
+       if ( setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,&dummy,sizeof(dummy)) == -1 )
+               return -1;
+}
 #endif
+       return 0;
+}
+
+/*
+ * check the socket for errors after select returned.
+ */
+static int
+ldap_pvt_is_socket_ready(LDAP *ld, int s)
+{
+       osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0);
+
+#define TRACE \
+{ \
+       osip_debug(ld, \
+               "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \
+               s, \
+               errno, \
+               strerror(errno) ); \
+}
+
 #ifdef notyet
-               status = 1;
-               if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
-                       Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
-                           s, 0, 0 );
+/* #ifdef SO_ERROR */
+{
+       int so_errno;
+       int dummy = sizeof(so_errno);
+       if ( getsockopt(s,SOL_SOCKET,SO_ERROR,&so_errno,&dummy) == -1 )
+               return -1;
+       if ( so_errno ) {
+               ldap_pvt_set_errno(so_errno);
+               TRACE;
+               return -1;
+       }
+       return 0;
+}
+#else
+{
+       /* error slippery */
+       struct sockaddr_in sin;
+       char ch;
+       int dummy = sizeof(sin);
+       if ( getpeername(s, (struct sockaddr *) &sin, &dummy) == -1 ) {
+               read(s, &ch, 1);
+#ifdef HAVE_WINSOCK
+               ldap_pvt_set_errno( WSAGetLastError() );
+#endif
+               TRACE;
+               return -1;
                }
-#endif /* notyet */
-               (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
-               sin.sin_family = AF_INET;
-               sin.sin_port = port;
-               SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
-                   ( use_hp ? (char *) hp->h_addr_list[ i ] :
-                   (char *) &address ), sizeof( sin.sin_addr.s_addr) );
-
-               if ( connect( s, (struct sockaddr *)&sin,
-                   sizeof( struct sockaddr_in )) >= 0 ) {
-                       connected = 1;
-                       rc = 0;
-                       break;
-               } else {
+       return 0;
+}
+#endif
+       return -1;
+#undef TRACE
+}
+
+static int
+ldap_pvt_connect(LDAP *ld, int s, struct sockaddr_in *sin, int async)
+{
+       struct timeval  tv, *opt_tv=NULL;
+       fd_set          wfds, *z=NULL;
+
+       if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) {
+               tv.tv_usec = opt_tv->tv_usec;
+               tv.tv_sec = opt_tv->tv_sec;
+       }
+
+       osip_debug(ld, "ldap_connect_timeout: fd: %d tm: %d async: %d\n",
+                       s, opt_tv ? tv.tv_sec : -1, async);
+
+       if ( ldap_pvt_ndelay_on(ld, s) == -1 )
+               return ( -1 );
+
+       if ( connect(s, (struct sockaddr *) sin, sizeof(struct sockaddr_in)) == 0 )
+       {
+               if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+                       return ( -1 );
+               return ( 0 );
+       }
+
 #ifdef HAVE_WINSOCK
-                       errno = WSAGetLastError();
+       ldap_pvt_set_errno( WSAGetLastError() );
 #endif
+
+       if ( (errno != EINPROGRESS) && (errno != EWOULDBLOCK) )
+               return ( -1 );
+       
 #ifdef notyet
-#ifdef EAGAIN
-                       if ( errno == EINPROGRESS || errno == EAGAIN ) {
-#else /* EAGAIN */
-                       if ( errno == EINPROGRESS ) {
-#endif /* EAGAIN */
-                               Debug( LDAP_DEBUG_TRACE,
-                                       "connect would block...\n", 0, 0, 0 );
-                               rc = -2;
-                               break;
-                       }
-#endif /* notyet */
+       if ( async ) return ( -2 );
+#endif
 
-#ifdef LDAP_DEBUG              
-                       if ( ldap_debug & LDAP_DEBUG_TRACE ) {
-                               perror( (char *)inet_ntoa( sin.sin_addr ));
-                       }
+       FD_ZERO(&wfds); FD_SET(s, &wfds );
+
+       if ( select(s + 1, z, &wfds, z, opt_tv ? &tv : NULL) == -1)
+               return ( -1 );
+
+       if ( FD_ISSET(s, &wfds) ) {
+               if ( ldap_pvt_is_socket_ready(ld, s) == -1 )
+                       return ( -1 );
+               if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+                       return ( -1 );
+               return ( 0 );
+       }
+       osip_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0);
+       ldap_pvt_set_errno( ETIMEDOUT );
+       return ( -1 );
+}
+
+static int
+ldap_pvt_inet_aton( LDAP *ld, const char *host, struct in_addr *in)
+{
+#ifdef notyet
+/* #ifdef HAVE_INET_ATON */
+       return inet_aton( host, in );
+#else
+{
+       unsigned long u = inet_addr( host );
+       if ( u != 0xffffffff || u != (unsigned long) -1 ) {
+               in->s_addr = u;
+               return 1;
+       }
+}
+#endif
+       return 0;
+}
+
+
+int
+ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
+               unsigned long address, int port, int async)
+{
+       struct sockaddr_in      sin;
+       struct in_addr          in;
+       ber_socket_t            s = AC_SOCKET_INVALID;
+       int                     rc, i, use_hp = 0;
+       struct hostent          *hp, he_buf;
+       int                     local_h_errno;
+       char                    *ha_buf=NULL, *p, *q;
+
+       osip_debug(ld, "ldap_connect_to_host\n",0,0,0);
+       
+       if (host != NULL) {
+               if (! ldap_pvt_inet_aton( ld, host, &in) ) {
+                       rc = ldap_pvt_gethostbyname_a(host, &he_buf, &ha_buf,
+                                       &hp, &local_h_errno);
+
+                       if ( rc < 0 )
+                               ; /*XXX NO MEMORY? */
+
+                       if ( (rc < 0) || (hp == NULL) ) {
+#ifdef HAVE_WINSOCK
+                               ldap_pvt_set_errno( WSAGetLastError() );
+#else
+                               /* not exactly right, but... */
+                               ldap_pvt_set_errno( EHOSTUNREACH );
 #endif
-                       tcp_close( s );
-                       if ( !use_hp ) {
-                               break;
+                               if (ha_buf) LDAP_FREE(ha_buf);
+                               return -1;
                        }
+                       use_hp = 1;
                }
+               address = in.s_addr;
        }
 
-       ber_pvt_sb_set_desc( sb, s );           
+       rc = s = -1;
+       for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
 
-       if ( connected ) {
+               if ( (s = ldap_pvt_socket( ld )) == -1 )
+                       /* use_hp ? continue : break; */
+                       break;
           
-#ifdef notyet
-               status = 0;
-               if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
-                       Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
-                           s, 0, 0 );
+               if ( ldap_pvt_prepare_socket(ld, s) == -1 ) {
+                       ldap_pvt_close_socket(ld, s);
+                       /* use_hp ? continue : break; */
+                       break;
                }
-#endif /* notyet */
 
-               Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
-                   s, (char *) inet_ntoa( sin.sin_addr ), 0 );
-       }
+               (void)memset((char *)&sin, 0, sizeof(struct sockaddr_in));
+               sin.sin_family = AF_INET;
+               sin.sin_port = port;
+               p = (char *)&sin.sin_addr.s_addr;
+               q = use_hp ? (char *)hp->h_addr_list[i] : (char *)&address;
+               SAFEMEMCPY(p, q, sizeof(p) );
 
-       DO_RETURN( rc );
-}
+               osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
+                               inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),0);
+
+               rc = ldap_pvt_connect(ld, s, &sin, async);
    
-#undef DO_RETURN
+               if ( (rc == 0) || (rc == -2) ) {
+                       ber_pvt_sb_set_desc( sb, s );
+                       break;
+               }
 
+               ldap_pvt_close_socket(ld, s);
+
+               if (!use_hp)
+                       break;
+       }
+       if (ha_buf) LDAP_FREE(ha_buf);
+       return rc;
+}
 
 void
 ldap_close_connection( Sockbuf *sb )
index 39b3263e4c6dd2b04505c630b7e300fe7924ca84..93ce360d754fb1039499e750eb5336e8fe5cd88d 100644 (file)
@@ -133,6 +133,16 @@ ldap_ld_free(
                ld->ld_options.ldo_defhost = NULL;
        }
 
+       if ( ld->ld_options.ldo_tm_api != NULL ) {
+               LDAP_FREE( ld->ld_options.ldo_tm_api );
+               ld->ld_options.ldo_tm_api = NULL;
+       }
+
+       if ( ld->ld_options.ldo_tm_net != NULL ) {
+               LDAP_FREE( ld->ld_options.ldo_tm_net );
+               ld->ld_options.ldo_tm_net = NULL;
+       }
+
        ber_pvt_sb_destroy( &(ld->ld_sb) );   
    
        LDAP_FREE( (char *) ld );