diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 73b0aa999d..844fd4cdc2 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -42,6 +42,9 @@ #define SASL_MIN_BUFF_SIZE 4096 #endif +#undef TV2MILLISEC +#define TV2MILLISEC(tv) (((tv)->sec * 1000) + ((tv)->tv_usec/1000)) + /* * Support needed if the library is running in the kernel */ diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 7399fe5bd2..45b1f9500d 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -210,12 +210,6 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, { int rc; struct timeval tv, *opt_tv=NULL; -#ifndef HAVE_POLL - fd_set wfds, *z=NULL; -#ifdef HAVE_WINSOCK - fd_set efds; -#endif -#endif #ifdef LDAP_CONNECTIONLESS /* We could do a connect() but that would interfere with @@ -259,60 +253,86 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, #endif #ifdef HAVE_POLL - assert(0); -#else - FD_ZERO(&wfds); - FD_SET(s, &wfds ); + { + struct pollfd fd; + int timeout = INFTIM; -#ifdef HAVE_WINSOCK - FD_ZERO(&efds); - FD_SET(s, &efds ); -#endif + if( opt_tv != NULL ) timeout = TV2MILLISEC( &tv ); - do { - 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 )); + fd.fd = s; + fd.events = POLLOUT; - if( rc == AC_SOCKET_ERROR ) return rc; + 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 )); -#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_pvt_connect: error on socket %d: " - "errno: %d (%s)\n", s, errno, sock_errstr(errno)); - return -1; + if( rc == AC_SOCKET_ERROR ) return rc; + + if( fd.revents & POLLOUT ) { + 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 ( FD_ISSET(s, &wfds) ) { + FD_ZERO(&wfds); + FD_SET(s, &wfds ); + +#ifdef HAVE_WINSOCK + FD_ZERO(&efds); + FD_SET(s, &efds ); +#endif + + do { + 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 )); + + if( rc == AC_SOCKET_ERROR ) return rc; + +#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_pvt_connect: 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 ); - return ( 0 ); + 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); ldap_pvt_set_errno( ETIMEDOUT ); - return ( -1 ); + return -1; } #ifndef HAVE_INET_ATON diff --git a/libraries/libldap/os-local.c b/libraries/libldap/os-local.c index 43d55f513d..ee047dc4c2 100644 --- a/libraries/libldap/os-local.c +++ b/libraries/libldap/os-local.c @@ -216,14 +216,40 @@ sendcred: #endif #ifdef HAVE_POLL - assert(0); + { + struct pollfd fd; + int timeout = INFTIM; + + if( opt_tv != NULL ) timeout = TV2MILLISEC( &tv ); + + fd.fd = s; + fd.events = POLLOUT; + + 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( fd.revents & POLLOUT ) { + if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1; + if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; +#ifdef DO_SENDMSG + goto sendcred; +#else + return ( 0 ); +#endif + } + } #else { - fd_set wfds, *z=NULL; - FD_ZERO(&wfds); - FD_SET(s, &wfds ); + fd_set wfds, *z=NULL; do { + FD_ZERO(&wfds); + FD_SET(s, &wfds ); rc = select( ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL ); } while( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART ));