#define LDAP_OPT_REFERRAL_URLS      0x5007  /* Referral URLs */
 #define LDAP_OPT_SOCKBUF            0x5008  /* sockbuf */
 #define LDAP_OPT_DEFBASE               0x5009  /* searchbase */
+#define        LDAP_OPT_CONNECT_ASYNC          0x5010  /* create connections asynchronously */
 
 /* OpenLDAP TLS options */
 #define LDAP_OPT_X_TLS                         0x6000
 #define LDAP_MORE_RESULTS_TO_RETURN            (-15)   /* Obsolete */
 #define LDAP_CLIENT_LOOP                               (-16)
 #define LDAP_REFERRAL_LIMIT_EXCEEDED   (-17)
+#define        LDAP_X_CONNECTING                       (-18)
 
 
 /*
 
 #define LDAP_BOOL_REFERRALS            0
 #define LDAP_BOOL_RESTART              1
 #define LDAP_BOOL_TLS                  3
+#define        LDAP_BOOL_CONNECT_ASYNC         4
 
 #define LDAP_BOOLEANS  unsigned long
 #define LDAP_BOOL(n)   ((LDAP_BOOLEANS)1 << (n))
        const struct timeval *tm );
 LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb,
        int proto, const char *host, int port, int async );
+LDAP_F (int) ldap_int_poll( LDAP *ld, ber_socket_t s,
+       struct timeval *tvp );
 
 #if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || \
        defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
 
 
                return LDAP_OPT_SUCCESS;
 
+       case LDAP_OPT_CONNECT_ASYNC:
+               * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
+               return LDAP_OPT_SUCCESS;
+               
        case LDAP_OPT_RESULT_CODE:
                if(ld == NULL) {
                        /* bad param */
                        LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
                }
                return LDAP_OPT_SUCCESS;
+
+       case LDAP_OPT_CONNECT_ASYNC:
+               if(invalue == LDAP_OPT_OFF) {
+                       LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC);
+               } else {
+                       LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
+               }
+               return LDAP_OPT_SUCCESS;
        }
 
        /* options which can withstand invalue == NULL */
 
 
 #endif /* HAVE_WINSOCK */
 
+/* NOTE: this is identical to analogous code in os-local.c */
+int
+ldap_int_poll(
+       LDAP *ld,
+       ber_socket_t s,
+       struct timeval *tvp )
+{
+       int             timeout = INFTIM;
+       struct timeval  tv = { 0 };
+       int             rc;
+               
+       if ( tvp != NULL ) {
+               tv = *tvp;
+               timeout = TV2MILLISEC( tvp );
+       }
+
+       osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n",
+               s, tvp ? tvp->tv_sec : -1L, 0);
+
+#ifdef HAVE_POLL
+       {
+               struct pollfd fd;
+
+               fd.fd = s;
+               fd.events = POLL_WRITE;
+
+               do {
+                       fd.revents = 0;
+                       rc = poll( &fd, 1, timeout );
+               
+               } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
+                       LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
+
+               if ( rc == AC_SOCKET_ERROR ) {
+                       return rc;
+               }
+
+               if ( timeout == 0 && rc == 0 ) {
+                       return -2;
+               }
+
+               if ( fd.revents & POLL_WRITE ) {
+                       if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
+                               return -1;
+                       }
+
+                       if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) {
+                               return -1;
+                       }
+                       return 0;
+               }
+       }
+#else
+       {
+               fd_set          wfds, *z = NULL;
+#ifdef HAVE_WINSOCK
+               fd_set          efds;
+#endif
+
+#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
+               if ( s >= FD_SETSIZE ) {
+                       rc = AC_SOCKET_ERROR;
+                       tcp_close( s );
+                       ldap_pvt_set_errno( EMFILE );
+                       return rc;
+               }
+#endif
+
+               do {
+                       FD_ZERO(&wfds);
+                       FD_SET(s, &wfds );
+
+#ifdef HAVE_WINSOCK
+                       FD_ZERO(&efds);
+                       FD_SET(s, &efds );
+#endif
+
+                       rc = select( ldap_int_tblsize, z, &wfds,
+#ifdef HAVE_WINSOCK
+                               &efds,
+#else
+                               z,
+#endif
+                               tvp ? &tv : NULL );
+               } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
+                       LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
+
+               if ( rc == AC_SOCKET_ERROR ) {
+                       return rc;
+               }
+
+               if ( timeout == 0 && rc == 0 ) {
+                       return -2;
+               }
+
+#ifdef HAVE_WINSOCK
+               /* This means the connection failed */
+               if ( FD_ISSET(s, &efds) ) {
+                       int so_errno;
+                       int dummy = sizeof(so_errno);
+                       if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
+                               (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
+                       {
+                               /* impossible */
+                               so_errno = WSAGetLastError();
+                       }
+                       ldap_pvt_set_errno( so_errno );
+                       osip_debug(ld, "ldap_int_poll: error on socket %d: "
+                              "errno: %d (%s)\n", s, errno, sock_errstr( errno ));
+                       return -1;
+               }
+#endif
+               if ( FD_ISSET(s, &wfds) ) {
+#ifndef HAVE_WINSOCK
+                       if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
+                               return -1;
+                       }
+#endif
+                       if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
+                               return -1;
+                       }
+                       return 0;
+               }
+       }
+#endif
+
+       osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0);
+       ldap_pvt_set_errno( ETIMEDOUT );
+       return -1;
+}
+
 static int
 ldap_pvt_connect(LDAP *ld, ber_socket_t s,
        struct sockaddr *sin, socklen_t addrlen,
                tv = *opt_tv;
        }
 
-       osip_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n",
+       osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
                        s, opt_tv ? tv.tv_sec : -1L, async);
 
        if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 )
                return ( -1 );
        }
        
-#ifdef notyet
-       if ( async ) return ( -2 );
-#endif
+       if ( async ) {
+               /* caller will call ldap_int_poll() as appropriate? */
+               return ( -2 );
+       }
+
+       rc = ldap_int_poll( ld, s, opt_tv );
 
+#if 0
 #ifdef HAVE_POLL
        {
                struct pollfd fd;
        }
 #endif
 
-       osip_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0);
-       ldap_pvt_set_errno( ETIMEDOUT );
-       return -1;
+#endif
+
+       osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);
+       return rc;
 }
 
 #ifndef HAVE_INET_ATON
 
                rc = ldap_pvt_connect( ld, s,
                        sai->ai_addr, sai->ai_addrlen, async );
-               if ( (rc == 0) || (rc == -2) ) {
+               if ( rc == 0 || rc == -2 ) {
                        ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
                        break;
                }
 
                }
        }
 
+       /* async connect... */
+       if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) {
+               ber_socket_t    sd = AC_SOCKET_ERROR;
+               struct timeval  tv = { 0 };
+
+               ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd );
+
+               /* poll ... */
+               switch ( ldap_int_poll( ld, sd, &tv ) ) {
+               case 0:
+                       /* go on! */
+                       lc->lconn_status = LDAP_CONNST_CONNECTED;
+                       break;
+
+               case -2:
+                       /* caller will have to call again */
+                       ld->ld_errno = LDAP_X_CONNECTING;
+                       /* fallthru */
+
+               default:
+                       /* error */
+                       break;
+               }
+       }
+
        if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
-               ber_free( ber, 1 );
                if ( ld->ld_errno == LDAP_SUCCESS ) {
                        ld->ld_errno = LDAP_SERVER_DOWN;
                }
+
+               ber_free( ber, 1 );
                if ( incparent ) {
                        /* Forget about the bind */
                        --parentreq->lr_outrefcnt; 
        int connect, LDAPreqinfo *bind )
 {
        LDAPConn        *lc;
+       int             async = 0;
 
        Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
                use_ldsb, connect, (bind != NULL) );
        if ( connect ) {
                LDAPURLDesc     **srvp, *srv = NULL;
 
+               async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );
+
                for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
-                       if ( ldap_int_open_connection( ld, lc, *srvp, 0 ) != -1 )
+                       if ( ldap_int_open_connection( ld, lc, *srvp, async) != -1 )
                        {
                                srv = *srvp;
 
                lc->lconn_server = ldap_url_dup( srv );
        }
 
-       lc->lconn_status = LDAP_CONNST_CONNECTED;
+       lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
 #ifdef LDAP_R_COMPILE
        ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
 #endif
                }
                Debug( LDAP_DEBUG_TRACE, "  refcnt: %d  status: %s\n", lc->lconn_refcnt,
                        ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET )
-                       ?  "NeedSocket" : ( lc->lconn_status == LDAP_CONNST_CONNECTING )
-                       ? "Connecting" : "Connected", 0 );
+                               ? "NeedSocket" :
+                               ( lc->lconn_status == LDAP_CONNST_CONNECTING )
+                                       ? "Connecting" : "Connected", 0 );
                Debug( LDAP_DEBUG_TRACE, "  last used: %s%s\n",
                        ldap_pvt_ctime( &lc->lconn_lastused, timebuf ),
                        lc->lconn_rebind_inprogress ? "  rebind in progress" : "", 0 );