/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2007 The OpenLDAP Foundation.
* Portions Copyright 1999 Lars Uffmann.
* All rights reserved.
*
#endif /* HAVE_WINSOCK */
-static int
-ldap_pvt_connect(LDAP *ld, ber_socket_t s,
- struct sockaddr *sin, socklen_t addrlen,
- int async)
+/* 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 rc, err;
- struct timeval tv = { 0 },
- *opt_tv = NULL;
-
-#ifdef LDAP_CONNECTIONLESS
- /* We could do a connect() but that would interfere with
- * attempts to poll a broadcast address
- */
- if (LDAP_IS_UDP(ld)) {
- if (ld->ld_options.ldo_peer)
- ldap_memfree(ld->ld_options.ldo_peer);
- ld->ld_options.ldo_peer=ldap_memalloc(sizeof(struct sockaddr));
- AC_MEMCPY(ld->ld_options.ldo_peer,sin,sizeof(struct sockaddr));
- return ( 0 );
- }
-#endif
- opt_tv = ld->ld_options.ldo_tm_net;
- if ( opt_tv != NULL ) {
- tv = *opt_tv;
- }
-
- osip_debug(ld, "ldap_connect_timeout: 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 );
-
- if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
- if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
- return ( -1 );
- return ( 0 );
- }
+ int rc;
+
- err = sock_errno();
- if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
- return ( -1 );
- }
-
-#ifdef notyet
- if ( async ) return ( -2 );
-#endif
+ osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n",
+ s, tvp ? tvp->tv_sec : -1L, 0);
#ifdef HAVE_POLL
{
struct pollfd fd;
int timeout = INFTIM;
- if( opt_tv != NULL ) timeout = TV2MILLISEC( &tv );
-
fd.fd = s;
fd.events = POLL_WRITE;
+ if ( tvp != NULL ) {
+ timeout = TV2MILLISEC( tvp );
+ }
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 ));
+
+ } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
+ LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
- if( rc == AC_SOCKET_ERROR ) return rc;
+ if ( rc == AC_SOCKET_ERROR ) {
+ return rc;
+ }
- 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 );
+ 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;
+ fd_set wfds, *z = NULL;
#ifdef HAVE_WINSOCK
fd_set efds;
#endif
+ struct timeval tv = { 0 };
#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
if ( s >= FD_SETSIZE ) {
}
#endif
+ if ( tvp != NULL ) {
+ tv = *tvp;
+ }
+
do {
FD_ZERO(&wfds);
FD_SET(s, &wfds );
FD_SET(s, &efds );
#endif
- rc = select(ldap_int_tblsize, z, &wfds,
+ rc = select( ldap_int_tblsize, z, &wfds,
#ifdef HAVE_WINSOCK
&efds,
#else
z,
#endif
- opt_tv ? &tv : NULL);
- } while( rc == AC_SOCKET_ERROR && errno == EINTR &&
- LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART ));
+ 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 ( rc == AC_SOCKET_ERROR ) {
+ return rc;
+ }
+
+ if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 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,
+ 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_pvt_connect: error on socket %d: "
- "errno: %d (%s)\n", s, errno, sock_errstr(errno));
- return -1;
+ {
+ /* 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;
+ if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
+ return -1;
+ }
#endif
- if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
+ return -1;
+ }
return 0;
}
}
#endif
- osip_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0);
+ 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,
+ int async)
+{
+ int rc, err;
+ struct timeval tv, *opt_tv = NULL;
+
+#ifdef LDAP_CONNECTIONLESS
+ /* We could do a connect() but that would interfere with
+ * attempts to poll a broadcast address
+ */
+ if (LDAP_IS_UDP(ld)) {
+ if (ld->ld_options.ldo_peer)
+ ldap_memfree(ld->ld_options.ldo_peer);
+ ld->ld_options.ldo_peer=ldap_memalloc(sizeof(struct sockaddr));
+ AC_MEMCPY(ld->ld_options.ldo_peer,sin,sizeof(struct sockaddr));
+ return ( 0 );
+ }
+#endif
+ if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
+ tv = ld->ld_options.ldo_tm_net;
+ opt_tv = &tv;
+ }
+
+ 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 );
+
+ if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
+ if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
+ return ( -1 );
+ return ( 0 );
+ }
+
+ err = sock_errno();
+ if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
+ return ( -1 );
+ }
+
+ if ( async ) {
+ /* caller will call ldap_int_poll() as appropriate? */
+ return ( -2 );
+ }
+
+ rc = ldap_int_poll( ld, s, opt_tv );
+
+ osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);
+
+ return rc;
+}
+
#ifndef HAVE_INET_ATON
int
ldap_pvt_inet_aton( const char *host, struct in_addr *in)
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;
}
return rc;
}
-#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || \
- defined( HAVE_CYRUS_SASL )
+#if defined( HAVE_CYRUS_SASL )
char *
ldap_host_connected_to( Sockbuf *sb, const char *host )
{