17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
87c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
97c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
107c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
137c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
147c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing
157c478bd9Sstevel@tonic-gate * rights and limitations under the License.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
187c478bd9Sstevel@tonic-gate * March 31, 1998.
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
217c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
227c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
237c478bd9Sstevel@tonic-gate * Rights Reserved.
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * Contributor(s):
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Regents of the University of Michigan.
297c478bd9Sstevel@tonic-gate * All rights reserved.
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * os-ip.c -- platform-specific TCP & UDP related code
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #if 0
36*55fea89dSDan Cross #ifndef lint
377c478bd9Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
387c478bd9Sstevel@tonic-gate #endif
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #include "ldap-int.h"
427c478bd9Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
437c478bd9Sstevel@tonic-gate #include <signal.h>
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
477c478bd9Sstevel@tonic-gate #include <poll.h>
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
527c478bd9Sstevel@tonic-gate #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) == INVALID_SOCKET)
537c478bd9Sstevel@tonic-gate #else
54*55fea89dSDan Cross #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) < 0 )
557c478bd9Sstevel@tonic-gate #endif
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #define NSLDAPI_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * Structures and union for tracking status of network sockets
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
657c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo { /* used with native OS poll() */
667c478bd9Sstevel@tonic-gate struct pollfd *ossi_pollfds;
677c478bd9Sstevel@tonic-gate int ossi_pollfds_size;
687c478bd9Sstevel@tonic-gate };
697c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
707c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo { /* used with native OS select() */
717c478bd9Sstevel@tonic-gate fd_set ossi_readfds;
727c478bd9Sstevel@tonic-gate fd_set ossi_writefds;
737c478bd9Sstevel@tonic-gate fd_set ossi_use_readfds;
747c478bd9Sstevel@tonic-gate fd_set ossi_use_writefds;
757c478bd9Sstevel@tonic-gate };
767c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo { /* used with ext. I/O poll() callback */
797c478bd9Sstevel@tonic-gate LDAP_X_PollFD *cbsi_pollfds;
807c478bd9Sstevel@tonic-gate int cbsi_pollfds_size;
817c478bd9Sstevel@tonic-gate };
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate * NSLDAPI_CB_POLL_MATCH() evaluates to non-zero (true) if the Sockbuf *sdp
857c478bd9Sstevel@tonic-gate * matches the LDAP_X_PollFD pollfd.
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
887c478bd9Sstevel@tonic-gate #define NSLDAPI_CB_POLL_SD_CAST (unsigned int)
897c478bd9Sstevel@tonic-gate #else
907c478bd9Sstevel@tonic-gate #define NSLDAPI_CB_POLL_SD_CAST
917c478bd9Sstevel@tonic-gate #endif
927c478bd9Sstevel@tonic-gate #if defined(LDAP_SASLIO_HOOKS)
937c478bd9Sstevel@tonic-gate #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
947c478bd9Sstevel@tonic-gate ( ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd)) && \
957c478bd9Sstevel@tonic-gate (((sbp)->sb_sasl_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) || \
967c478bd9Sstevel@tonic-gate ((sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) ) )
977c478bd9Sstevel@tonic-gate #else
987c478bd9Sstevel@tonic-gate #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
997c478bd9Sstevel@tonic-gate ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd) && \
1007c478bd9Sstevel@tonic-gate (sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg)
1017c478bd9Sstevel@tonic-gate #endif
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate struct nsldapi_iostatus_info {
1057c478bd9Sstevel@tonic-gate int ios_type;
1067c478bd9Sstevel@tonic-gate #define NSLDAPI_IOSTATUS_TYPE_OSNATIVE 1 /* poll() or select() */
1077c478bd9Sstevel@tonic-gate #define NSLDAPI_IOSTATUS_TYPE_CALLBACK 2 /* poll()-like */
1087c478bd9Sstevel@tonic-gate int ios_read_count;
1097c478bd9Sstevel@tonic-gate int ios_write_count;
1107c478bd9Sstevel@tonic-gate union {
1117c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo ios_osinfo;
1127c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo ios_cbinfo;
1137c478bd9Sstevel@tonic-gate } ios_status;
1147c478bd9Sstevel@tonic-gate };
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1187c478bd9Sstevel@tonic-gate static int nsldapi_add_to_os_pollfds( int fd,
1197c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short events );
1207c478bd9Sstevel@tonic-gate static int nsldapi_clear_from_os_pollfds( int fd,
1217c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short events );
1227c478bd9Sstevel@tonic-gate static int nsldapi_find_in_os_pollfds( int fd,
1237c478bd9Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short revents );
1247c478bd9Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate static int nsldapi_iostatus_init_nolock( LDAP *ld );
1277c478bd9Sstevel@tonic-gate static int nsldapi_add_to_cb_pollfds( Sockbuf *sb,
1287c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events );
1297c478bd9Sstevel@tonic-gate static int nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
1307c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events );
1317c478bd9Sstevel@tonic-gate static int nsldapi_find_in_cb_pollfds( Sockbuf *sb,
1327c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short revents );
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate #ifdef irix
1367c478bd9Sstevel@tonic-gate #ifndef _PR_THREADS
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate * XXXmcs: on IRIX NSPR's poll() and select() wrappers will crash if NSPR
1397c478bd9Sstevel@tonic-gate * has not been initialized. We work around the problem by bypassing
1407c478bd9Sstevel@tonic-gate * the NSPR wrapper functions and going directly to the OS' functions.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate #define NSLDAPI_POLL _poll
1437c478bd9Sstevel@tonic-gate #define NSLDAPI_SELECT _select
1447c478bd9Sstevel@tonic-gate extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
1457c478bd9Sstevel@tonic-gate extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
1467c478bd9Sstevel@tonic-gate fd_set *exceptfds, struct timeval *timeout);
1477c478bd9Sstevel@tonic-gate #else /* _PR_THREADS */
1487c478bd9Sstevel@tonic-gate #define NSLDAPI_POLL poll
1497c478bd9Sstevel@tonic-gate #define NSLDAPI_SELECT select
1507c478bd9Sstevel@tonic-gate #endif /* else _PR_THREADS */
1517c478bd9Sstevel@tonic-gate #else /* irix */
1527c478bd9Sstevel@tonic-gate #define NSLDAPI_POLL poll
1537c478bd9Sstevel@tonic-gate #define NSLDAPI_SELECT select
1547c478bd9Sstevel@tonic-gate #endif /* else irix */
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate static LBER_SOCKET nsldapi_os_socket( LDAP *ld, int secure, int domain,
1587c478bd9Sstevel@tonic-gate int type, int protocol );
1597c478bd9Sstevel@tonic-gate static int nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp );
1607c478bd9Sstevel@tonic-gate static int nsldapi_os_connect_with_to( LBER_SOCKET s, struct sockaddr *name,
1617c478bd9Sstevel@tonic-gate int namelen, LDAP *ld);
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate * Function typedefs used by nsldapi_try_each_host()
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate typedef LBER_SOCKET (NSLDAPI_SOCKET_FN)( LDAP *ld, int secure, int domain,
1677c478bd9Sstevel@tonic-gate int type, int protocol );
1687c478bd9Sstevel@tonic-gate typedef int (NSLDAPI_IOCTL_FN)( LBER_SOCKET s, int option, int *statusp );
1697c478bd9Sstevel@tonic-gate typedef int (NSLDAPI_CONNECT_WITH_TO_FN )( LBER_SOCKET s, struct sockaddr *name,
1707c478bd9Sstevel@tonic-gate int namelen, LDAP *ld);
1717c478bd9Sstevel@tonic-gate typedef int (NSLDAPI_CONNECT_FN )( LBER_SOCKET s, struct sockaddr *name,
1727c478bd9Sstevel@tonic-gate int namelen );
1737c478bd9Sstevel@tonic-gate typedef int (NSLDAPI_CLOSE_FN )( LBER_SOCKET s );
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate static int nsldapi_try_each_host( LDAP *ld, const char *hostlist, int defport,
1767c478bd9Sstevel@tonic-gate int secure, NSLDAPI_SOCKET_FN *socketfn, NSLDAPI_IOCTL_FN *ioctlfn,
1777c478bd9Sstevel@tonic-gate NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
1787c478bd9Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn );
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate static int
nsldapi_os_closesocket(LBER_SOCKET s)1827c478bd9Sstevel@tonic-gate nsldapi_os_closesocket( LBER_SOCKET s )
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate int rc;
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
1877c478bd9Sstevel@tonic-gate rc = closesocket( s );
1887c478bd9Sstevel@tonic-gate #else
1897c478bd9Sstevel@tonic-gate rc = close( s );
1907c478bd9Sstevel@tonic-gate #endif
1917c478bd9Sstevel@tonic-gate return( rc );
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate static LBER_SOCKET
nsldapi_os_socket(LDAP * ld,int secure,int domain,int type,int protocol)1967c478bd9Sstevel@tonic-gate nsldapi_os_socket( LDAP *ld, int secure, int domain, int type, int protocol )
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate int s, invalid_socket;
1997c478bd9Sstevel@tonic-gate char *errmsg = NULL;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate if ( secure ) {
2027c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
2037c478bd9Sstevel@tonic-gate nsldapi_strdup( dgettext(TEXT_DOMAIN,
2047c478bd9Sstevel@tonic-gate "secure mode not supported") ));
2057c478bd9Sstevel@tonic-gate return( -1 );
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate s = socket( domain, type, protocol );
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate * if the socket() call failed or it returned a socket larger
2127c478bd9Sstevel@tonic-gate * than we can deal with, return a "local error."
2137c478bd9Sstevel@tonic-gate */
2147c478bd9Sstevel@tonic-gate if ( NSLDAPI_INVALID_OS_SOCKET( s )) {
2157c478bd9Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN, "unable to create a socket");
2167c478bd9Sstevel@tonic-gate invalid_socket = 1;
2177c478bd9Sstevel@tonic-gate } else { /* valid socket -- check for overflow */
2187c478bd9Sstevel@tonic-gate invalid_socket = 0;
2197c478bd9Sstevel@tonic-gate #if !defined(NSLDAPI_HAVE_POLL) && !defined(_WINDOWS)
2207c478bd9Sstevel@tonic-gate /* not on Windows and do not have poll() */
2217c478bd9Sstevel@tonic-gate if ( s >= FD_SETSIZE ) {
2227c478bd9Sstevel@tonic-gate errmsg = "can't use socket >= FD_SETSIZE";
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate #endif
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate if ( errmsg != NULL ) { /* local socket error */
2287c478bd9Sstevel@tonic-gate if ( !invalid_socket ) {
2297c478bd9Sstevel@tonic-gate nsldapi_os_closesocket( s );
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate errmsg = nsldapi_strdup( errmsg );
2327c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, errmsg );
2337c478bd9Sstevel@tonic-gate return( -1 );
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate return( s );
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * Non-blocking connect call function
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate static int
nsldapi_os_connect_with_to(LBER_SOCKET sockfd,struct sockaddr * saptr,int salen,LDAP * ld)2457c478bd9Sstevel@tonic-gate nsldapi_os_connect_with_to(LBER_SOCKET sockfd, struct sockaddr *saptr,
2467c478bd9Sstevel@tonic-gate int salen, LDAP *ld)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate #ifndef _WINDOWS
2497c478bd9Sstevel@tonic-gate int flags;
2507c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
2517c478bd9Sstevel@tonic-gate int n, error;
2527c478bd9Sstevel@tonic-gate int len;
2537c478bd9Sstevel@tonic-gate fd_set rset, wset;
2547c478bd9Sstevel@tonic-gate struct timeval tval;
2557c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
2567c478bd9Sstevel@tonic-gate int nonblock = 1;
2577c478bd9Sstevel@tonic-gate int block = 0;
2587c478bd9Sstevel@tonic-gate fd_set eset;
2597c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
2607c478bd9Sstevel@tonic-gate int msec = ld->ld_connect_timeout; /* milliseconds */
2617c478bd9Sstevel@tonic-gate int continue_on_intr = 0;
2627c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
2637c478bd9Sstevel@tonic-gate hrtime_t start_time = 0, tmp_time, tv_time; /* nanoseconds */
2647c478bd9Sstevel@tonic-gate #else
2657c478bd9Sstevel@tonic-gate long start_time = 0, tmp_time; /* seconds */
2667c478bd9Sstevel@tonic-gate #endif
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_nonblock timeout: %d (msec)\n",
2707c478bd9Sstevel@tonic-gate msec, 0, 0);
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
2737c478bd9Sstevel@tonic-gate ioctlsocket(sockfd, FIONBIO, &nonblock);
2747c478bd9Sstevel@tonic-gate #else
2757c478bd9Sstevel@tonic-gate flags = fcntl(sockfd, F_GETFL, 0);
2767c478bd9Sstevel@tonic-gate fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
2777c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate error = 0;
2807c478bd9Sstevel@tonic-gate if ((n = connect(sockfd, saptr, salen)) < 0)
2817c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
2827c478bd9Sstevel@tonic-gate if ((n != SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) {
2837c478bd9Sstevel@tonic-gate #else
2847c478bd9Sstevel@tonic-gate if (errno != EINPROGRESS) {
2857c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
2867c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG
2877c478bd9Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_TRACE ) {
2887c478bd9Sstevel@tonic-gate perror("connect");
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate #endif
2917c478bd9Sstevel@tonic-gate return (-1);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /* success */
2957c478bd9Sstevel@tonic-gate if (n == 0)
2967c478bd9Sstevel@tonic-gate goto done;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate FD_ZERO(&rset);
2997c478bd9Sstevel@tonic-gate FD_SET(sockfd, &rset);
3007c478bd9Sstevel@tonic-gate wset = rset;
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
3037c478bd9Sstevel@tonic-gate eset = rset;
3047c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate if (msec < 0 && msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) {
3077c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "Invalid timeout value detected.."
3087c478bd9Sstevel@tonic-gate "resetting connect timeout to default value "
3097c478bd9Sstevel@tonic-gate "(LDAP_X_IO_TIMEOUT_NO_TIMEOUT\n", 0, 0, 0);
3107c478bd9Sstevel@tonic-gate msec = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
3117c478bd9Sstevel@tonic-gate } else {
3127c478bd9Sstevel@tonic-gate if (msec != 0) {
3137c478bd9Sstevel@tonic-gate tval.tv_sec = msec / MILLISEC;
3147c478bd9Sstevel@tonic-gate tval.tv_usec = (MICROSEC / MILLISEC) *
3157c478bd9Sstevel@tonic-gate (msec % MILLISEC);
3167c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3177c478bd9Sstevel@tonic-gate start_time = gethrtime();
31819449258SJosef 'Jeff' Sipek tv_time = MSEC2NSEC(msec);
3197c478bd9Sstevel@tonic-gate #else
3207c478bd9Sstevel@tonic-gate start_time = (long)time(NULL);
3217c478bd9Sstevel@tonic-gate #endif
3227c478bd9Sstevel@tonic-gate } else {
3237c478bd9Sstevel@tonic-gate tval.tv_sec = 0;
3247c478bd9Sstevel@tonic-gate tval.tv_usec = 0;
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate /* if timeval structure == NULL, select will block indefinitely */
3297c478bd9Sstevel@tonic-gate /* != NULL, and value == 0, select will */
3307c478bd9Sstevel@tonic-gate /* not block */
3317c478bd9Sstevel@tonic-gate /* Windows is a bit quirky on how it behaves w.r.t nonblocking */
3327c478bd9Sstevel@tonic-gate /* connects. If the connect fails, the exception fd, eset, is */
3337c478bd9Sstevel@tonic-gate /* set to show the failure. The first argument in select is */
3347c478bd9Sstevel@tonic-gate /* ignored */
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
3377c478bd9Sstevel@tonic-gate if ((n = select(sockfd +1, &rset, &wset, &eset,
3387c478bd9Sstevel@tonic-gate (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) {
3397c478bd9Sstevel@tonic-gate errno = WSAETIMEDOUT;
3407c478bd9Sstevel@tonic-gate return (-1);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate /* if wset is set, the connect worked */
3437c478bd9Sstevel@tonic-gate if (FD_ISSET(sockfd, &wset) || FD_ISSET(sockfd, &rset)) {
3447c478bd9Sstevel@tonic-gate len = sizeof(error);
3457c478bd9Sstevel@tonic-gate if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
3467c478bd9Sstevel@tonic-gate < 0)
3477c478bd9Sstevel@tonic-gate return (-1);
3487c478bd9Sstevel@tonic-gate goto done;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate /* if eset is set, the connect failed */
3527c478bd9Sstevel@tonic-gate if (FD_ISSET(sockfd, &eset)) {
3537c478bd9Sstevel@tonic-gate return (-1);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate /* failure on select call */
3577c478bd9Sstevel@tonic-gate if (n == SOCKET_ERROR) {
3587c478bd9Sstevel@tonic-gate perror("select error: SOCKET_ERROR returned");
359*55fea89dSDan Cross return (-1);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate #else
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate * if LDAP_BITOPT_RESTART and select() is interrupted
3647c478bd9Sstevel@tonic-gate * try again.
3657c478bd9Sstevel@tonic-gate */
3667c478bd9Sstevel@tonic-gate do {
3677c478bd9Sstevel@tonic-gate continue_on_intr = 0;
3687c478bd9Sstevel@tonic-gate if ((n = select(sockfd +1, &rset, &wset, NULL,
3697c478bd9Sstevel@tonic-gate (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? \
3707c478bd9Sstevel@tonic-gate &tval : NULL)) == 0) {
3717c478bd9Sstevel@tonic-gate errno = ETIMEDOUT;
3727c478bd9Sstevel@tonic-gate return (-1);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate if (n < 0) {
3757c478bd9Sstevel@tonic-gate if ((ld->ld_options & LDAP_BITOPT_RESTART) &&
3767c478bd9Sstevel@tonic-gate (errno == EINTR)) {
3777c478bd9Sstevel@tonic-gate continue_on_intr = 1;
3787c478bd9Sstevel@tonic-gate errno = 0;
3797c478bd9Sstevel@tonic-gate FD_ZERO(&rset);
3807c478bd9Sstevel@tonic-gate FD_SET(sockfd, &rset);
3817c478bd9Sstevel@tonic-gate wset = rset;
3827c478bd9Sstevel@tonic-gate /* honour the timeout */
3837c478bd9Sstevel@tonic-gate if ((msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) &&
3847c478bd9Sstevel@tonic-gate (msec != 0)) {
3857c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3867c478bd9Sstevel@tonic-gate tmp_time = gethrtime();
3877c478bd9Sstevel@tonic-gate if ((tv_time -=
3887c478bd9Sstevel@tonic-gate (tmp_time - start_time)) <= 0) {
3897c478bd9Sstevel@tonic-gate #else
3907c478bd9Sstevel@tonic-gate tmp_time = (long)time(NULL);
3917c478bd9Sstevel@tonic-gate if ((tval.tv_sec -=
3927c478bd9Sstevel@tonic-gate (tmp_time - start_time)) <= 0) {
3937c478bd9Sstevel@tonic-gate #endif
3947c478bd9Sstevel@tonic-gate /* timeout */
3957c478bd9Sstevel@tonic-gate errno = ETIMEDOUT;
3967c478bd9Sstevel@tonic-gate return (-1);
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3997c478bd9Sstevel@tonic-gate tval.tv_sec = tv_time / NANOSEC;
4007c478bd9Sstevel@tonic-gate tval.tv_usec = (tv_time % NANOSEC) /
4017c478bd9Sstevel@tonic-gate (NANOSEC / MICROSEC);
4027c478bd9Sstevel@tonic-gate #endif
4037c478bd9Sstevel@tonic-gate start_time = tmp_time;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate } else {
4067c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG
4077c478bd9Sstevel@tonic-gate perror("select error: ");
4087c478bd9Sstevel@tonic-gate #endif
4097c478bd9Sstevel@tonic-gate return (-1);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate } while (continue_on_intr == 1);
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
4157c478bd9Sstevel@tonic-gate len = sizeof(error);
4167c478bd9Sstevel@tonic-gate if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
4177c478bd9Sstevel@tonic-gate < 0)
4187c478bd9Sstevel@tonic-gate return (-1);
4197c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG
4207c478bd9Sstevel@tonic-gate } else if ( ldap_debug & LDAP_DEBUG_TRACE ) {
4217c478bd9Sstevel@tonic-gate perror("select error: sockfd not set");
4227c478bd9Sstevel@tonic-gate #endif
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate done:
4277c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
4287c478bd9Sstevel@tonic-gate ioctlsocket(sockfd, FIONBIO, &block);
4297c478bd9Sstevel@tonic-gate #else
4307c478bd9Sstevel@tonic-gate fcntl(sockfd, F_SETFL, flags);
4317c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate if (error) {
4347c478bd9Sstevel@tonic-gate errno = error;
4357c478bd9Sstevel@tonic-gate return (-1);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate return (0);
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate static int
4437c478bd9Sstevel@tonic-gate nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp )
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate int err;
4467c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
4477c478bd9Sstevel@tonic-gate u_long iostatus;
4487c478bd9Sstevel@tonic-gate #endif
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate if ( FIONBIO != option ) {
4517c478bd9Sstevel@tonic-gate return( -1 );
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
4557c478bd9Sstevel@tonic-gate iostatus = *(u_long *)statusp;
4567c478bd9Sstevel@tonic-gate err = ioctlsocket( s, FIONBIO, &iostatus );
4577c478bd9Sstevel@tonic-gate #else
4587c478bd9Sstevel@tonic-gate err = ioctl( s, FIONBIO, (caddr_t)statusp );
4597c478bd9Sstevel@tonic-gate #endif
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate return( err );
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate int
4667c478bd9Sstevel@tonic-gate nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *hostlist,
4677c478bd9Sstevel@tonic-gate int defport, int secure, char **krbinstancep )
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate * "defport" must be in host byte order
4707c478bd9Sstevel@tonic-gate * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
4717c478bd9Sstevel@tonic-gate * if -1 is returned, ld_errno is set
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate int s;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_to_host: %s, port: %d\n",
4777c478bd9Sstevel@tonic-gate NULL == hostlist ? "NULL" : hostlist, defport, 0 );
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * If an extended I/O connect callback has been defined, just use it.
4817c478bd9Sstevel@tonic-gate */
4827c478bd9Sstevel@tonic-gate if ( NULL != ld->ld_extconnect_fn ) {
4837c478bd9Sstevel@tonic-gate unsigned long connect_opts = 0;
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
4867c478bd9Sstevel@tonic-gate connect_opts |= LDAP_X_EXTIOF_OPT_NONBLOCKING;
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate if ( secure ) {
4897c478bd9Sstevel@tonic-gate connect_opts |= LDAP_X_EXTIOF_OPT_SECURE;
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate s = ld->ld_extconnect_fn( hostlist, defport,
4927c478bd9Sstevel@tonic-gate ld->ld_connect_timeout, connect_opts,
4937c478bd9Sstevel@tonic-gate ld->ld_ext_session_arg,
4947c478bd9Sstevel@tonic-gate &sb->sb_ext_io_fns.lbextiofn_socket_arg
4957c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
4967c478bd9Sstevel@tonic-gate , NULL );
4977c478bd9Sstevel@tonic-gate #else
4987c478bd9Sstevel@tonic-gate );
4997c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate } else {
5027c478bd9Sstevel@tonic-gate s = nsldapi_try_each_host( ld, hostlist,
5037c478bd9Sstevel@tonic-gate defport, secure, nsldapi_os_socket,
5047c478bd9Sstevel@tonic-gate nsldapi_os_ioctl, nsldapi_os_connect_with_to,
5057c478bd9Sstevel@tonic-gate NULL, nsldapi_os_closesocket );
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate if ( s < 0 ) {
5097c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
5107c478bd9Sstevel@tonic-gate return( -1 );
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate sb->sb_sd = s;
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate * Set krbinstancep (canonical name of host for use by Kerberos).
5177c478bd9Sstevel@tonic-gate */
5187c478bd9Sstevel@tonic-gate #ifdef KERBEROS
5197c478bd9Sstevel@tonic-gate char *p;
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate if (( *krbinstancep = nsldapi_host_connected_to( sb )) != NULL
5227c478bd9Sstevel@tonic-gate && ( p = strchr( *krbinstancep, '.' )) != NULL ) {
5237c478bd9Sstevel@tonic-gate *p = '\0';
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate #else /* KERBEROS */
5267c478bd9Sstevel@tonic-gate *krbinstancep = NULL;
5277c478bd9Sstevel@tonic-gate #endif /* KERBEROS */
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate return( 0 );
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate * Returns a socket number if successful and -1 if an error occurs.
5357c478bd9Sstevel@tonic-gate */
5367c478bd9Sstevel@tonic-gate static int
5377c478bd9Sstevel@tonic-gate nsldapi_try_each_host( LDAP *ld, const char *hostlist,
5387c478bd9Sstevel@tonic-gate int defport, int secure, NSLDAPI_SOCKET_FN *socketfn,
5397c478bd9Sstevel@tonic-gate NSLDAPI_IOCTL_FN *ioctlfn, NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
5407c478bd9Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn )
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate int rc, i, s, err, connected, use_hp;
5437c478bd9Sstevel@tonic-gate int parse_err, port;
5447c478bd9Sstevel@tonic-gate struct sockaddr_in sin;
5457c478bd9Sstevel@tonic-gate nsldapi_in_addr_t address;
5467c478bd9Sstevel@tonic-gate char **addrlist, *ldhpbuf, *ldhpbuf_allocd;
5477c478bd9Sstevel@tonic-gate char *host;
5487c478bd9Sstevel@tonic-gate LDAPHostEnt ldhent, *ldhp;
5497c478bd9Sstevel@tonic-gate struct hostent *hp;
5507c478bd9Sstevel@tonic-gate struct ldap_x_hostlist_status *status;
5517c478bd9Sstevel@tonic-gate #ifdef GETHOSTBYNAME_BUF_T
5527c478bd9Sstevel@tonic-gate GETHOSTBYNAME_BUF_T hbuf;
5537c478bd9Sstevel@tonic-gate struct hostent hent;
5547c478bd9Sstevel@tonic-gate #endif /* GETHOSTBYNAME_BUF_T */
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate connected = 0;
5577c478bd9Sstevel@tonic-gate parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port,
5587c478bd9Sstevel@tonic-gate &status );
5597c478bd9Sstevel@tonic-gate while ( !connected && LDAP_SUCCESS == parse_err && host != NULL ) {
5607c478bd9Sstevel@tonic-gate ldhpbuf_allocd = NULL;
5617c478bd9Sstevel@tonic-gate ldhp = NULL;
5627c478bd9Sstevel@tonic-gate hp = NULL;
5637c478bd9Sstevel@tonic-gate s = 0;
5647c478bd9Sstevel@tonic-gate use_hp = 0;
5657c478bd9Sstevel@tonic-gate addrlist = NULL;
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate if (( address = inet_addr( host )) == -1 ) {
5697c478bd9Sstevel@tonic-gate if ( ld->ld_dns_gethostbyname_fn == NULL ) {
5707c478bd9Sstevel@tonic-gate if (( hp = GETHOSTBYNAME( host, &hent, hbuf,
5717c478bd9Sstevel@tonic-gate sizeof(hbuf), &err )) != NULL ) {
5727c478bd9Sstevel@tonic-gate addrlist = hp->h_addr_list;
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate } else {
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate * DNS callback installed... use it.
5777c478bd9Sstevel@tonic-gate */
5787c478bd9Sstevel@tonic-gate #ifdef GETHOSTBYNAME_buf_t
5797c478bd9Sstevel@tonic-gate /* avoid allocation by using hbuf if large enough */
5807c478bd9Sstevel@tonic-gate if ( sizeof( hbuf ) < ld->ld_dns_bufsize ) {
5817c478bd9Sstevel@tonic-gate ldhpbuf = ldhpbuf_allocd
5827c478bd9Sstevel@tonic-gate = NSLDAPI_MALLOC( ld->ld_dns_bufsize );
5837c478bd9Sstevel@tonic-gate } else {
5847c478bd9Sstevel@tonic-gate ldhpbuf = (char *)hbuf;
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate #else /* GETHOSTBYNAME_buf_t */
5877c478bd9Sstevel@tonic-gate ldhpbuf = ldhpbuf_allocd = NSLDAPI_MALLOC(
5887c478bd9Sstevel@tonic-gate ld->ld_dns_bufsize );
5897c478bd9Sstevel@tonic-gate #endif /* else GETHOSTBYNAME_buf_t */
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if ( ldhpbuf == NULL ) {
5927c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY,
5937c478bd9Sstevel@tonic-gate NULL, NULL );
5947c478bd9Sstevel@tonic-gate ldap_memfree( host );
5957c478bd9Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
5967c478bd9Sstevel@tonic-gate return( -1 );
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if (( ldhp = ld->ld_dns_gethostbyname_fn( host,
6007c478bd9Sstevel@tonic-gate &ldhent, ldhpbuf, ld->ld_dns_bufsize, &err,
6017c478bd9Sstevel@tonic-gate ld->ld_dns_extradata )) != NULL ) {
6027c478bd9Sstevel@tonic-gate addrlist = ldhp->ldaphe_addr_list;
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate if ( addrlist == NULL ) {
6077c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
6087c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO( ld, EHOSTUNREACH ); /* close enough */
6097c478bd9Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
6107c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate ldap_memfree( host );
6137c478bd9Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
6147c478bd9Sstevel@tonic-gate return( -1 );
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate use_hp = 1;
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate rc = -1;
6207c478bd9Sstevel@tonic-gate for ( i = 0; !use_hp || ( addrlist[ i ] != 0 ); i++ ) {
6217c478bd9Sstevel@tonic-gate if ( -1 == ( s = (*socketfn)( ld, secure, AF_INET,
6227c478bd9Sstevel@tonic-gate SOCK_STREAM, 0 ))) {
6237c478bd9Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
6247c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate ldap_memfree( host );
6277c478bd9Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
6287c478bd9Sstevel@tonic-gate return( -1 );
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC ) {
6327c478bd9Sstevel@tonic-gate int iostatus = 1;
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate err = (*ioctlfn)( s, FIONBIO, &iostatus );
6357c478bd9Sstevel@tonic-gate if ( err == -1 ) {
6367c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
6377c478bd9Sstevel@tonic-gate "FIONBIO ioctl failed on %d\n",
6387c478bd9Sstevel@tonic-gate s, 0, 0 );
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
6437c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET;
6447c478bd9Sstevel@tonic-gate sin.sin_port = htons( (unsigned short)port );
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
6477c478bd9Sstevel@tonic-gate ( use_hp ? (char *) addrlist[ i ] :
6487c478bd9Sstevel@tonic-gate (char *) &address ), sizeof( sin.sin_addr.s_addr) );
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
6527c478bd9Sstevel@tonic-gate /*
6537c478bd9Sstevel@tonic-gate * Block all of the signals that might interrupt connect() since there
6547c478bd9Sstevel@tonic-gate * is an OS bug that causes connect() to fail if it is restarted. Look in
6557c478bd9Sstevel@tonic-gate * ns/netsite/ldap/include/portable.h for the definition of
6567c478bd9Sstevel@tonic-gate * LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
6577c478bd9Sstevel@tonic-gate */
6587c478bd9Sstevel@tonic-gate sigset_t ints_off, oldset;
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate sigemptyset( &ints_off );
6617c478bd9Sstevel@tonic-gate sigaddset( &ints_off, SIGALRM );
6627c478bd9Sstevel@tonic-gate sigaddset( &ints_off, SIGIO );
6637c478bd9Sstevel@tonic-gate sigaddset( &ints_off, SIGCLD );
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate sigprocmask( SIG_BLOCK, &ints_off, &oldset );
6667c478bd9Sstevel@tonic-gate #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
6677c478bd9Sstevel@tonic-gate
668*55fea89dSDan Cross if ( NULL != connectwithtofn ) {
6697c478bd9Sstevel@tonic-gate err = (*connectwithtofn)(s,
6707c478bd9Sstevel@tonic-gate (struct sockaddr *)&sin,
6717c478bd9Sstevel@tonic-gate sizeof(struct sockaddr_in),
6727c478bd9Sstevel@tonic-gate ld);
6737c478bd9Sstevel@tonic-gate } else {
6747c478bd9Sstevel@tonic-gate err = (*connectfn)(s,
6757c478bd9Sstevel@tonic-gate (struct sockaddr *)&sin,
6767c478bd9Sstevel@tonic-gate sizeof(struct sockaddr_in));
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
6797c478bd9Sstevel@tonic-gate /*
6807c478bd9Sstevel@tonic-gate * restore original signal mask
6817c478bd9Sstevel@tonic-gate */
6827c478bd9Sstevel@tonic-gate sigprocmask( SIG_SETMASK, &oldset, 0 );
6837c478bd9Sstevel@tonic-gate #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate if ( err >= 0 ) {
6877c478bd9Sstevel@tonic-gate connected = 1;
6887c478bd9Sstevel@tonic-gate rc = 0;
6897c478bd9Sstevel@tonic-gate break;
6907c478bd9Sstevel@tonic-gate } else {
6917c478bd9Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
6927c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
6937c478bd9Sstevel@tonic-gate if (err == -1 && WSAGetLastError() == WSAEWOULDBLOCK)
6947c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO( ld, EWOULDBLOCK );
6957c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */
6967c478bd9Sstevel@tonic-gate err = LDAP_GET_ERRNO( ld );
6977c478bd9Sstevel@tonic-gate if ( NSLDAPI_ERRNO_IO_INPROGRESS( err )) {
6987c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "connect would block...\n",
6997c478bd9Sstevel@tonic-gate 0, 0, 0 );
7007c478bd9Sstevel@tonic-gate rc = -2;
7017c478bd9Sstevel@tonic-gate break;
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG
7067c478bd9Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_TRACE ) {
7077c478bd9Sstevel@tonic-gate perror( (char *)inet_ntoa( sin.sin_addr ));
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate #endif
7107c478bd9Sstevel@tonic-gate (*closefn)( s );
7117c478bd9Sstevel@tonic-gate if ( !use_hp ) {
7127c478bd9Sstevel@tonic-gate break;
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate ldap_memfree( host );
7187c478bd9Sstevel@tonic-gate parse_err = ldap_x_hostlist_next( &host, &port, status );
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
7227c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate ldap_memfree( host );
7257c478bd9Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate if ( connected ) {
7287c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
7297c478bd9Sstevel@tonic-gate s, inet_ntoa( sin.sin_addr ), 0 );
7307c478bd9Sstevel@tonic-gate }
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate return( rc == 0 ? s : -1 );
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate void
7377c478bd9Sstevel@tonic-gate nsldapi_close_connection( LDAP *ld, Sockbuf *sb )
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate if ( ld->ld_extclose_fn == NULL ) {
7407c478bd9Sstevel@tonic-gate nsldapi_os_closesocket( sb->sb_sd );
7417c478bd9Sstevel@tonic-gate } else {
7427c478bd9Sstevel@tonic-gate ld->ld_extclose_fn( sb->sb_sd,
7437c478bd9Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg );
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate #ifdef KERBEROS
7497c478bd9Sstevel@tonic-gate char *
7507c478bd9Sstevel@tonic-gate nsldapi_host_connected_to( Sockbuf *sb )
7517c478bd9Sstevel@tonic-gate {
7527c478bd9Sstevel@tonic-gate struct hostent *hp;
7537c478bd9Sstevel@tonic-gate char *p;
7547c478bd9Sstevel@tonic-gate int len;
7557c478bd9Sstevel@tonic-gate struct sockaddr_in sin;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
7587c478bd9Sstevel@tonic-gate len = sizeof( sin );
7597c478bd9Sstevel@tonic-gate if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
7607c478bd9Sstevel@tonic-gate return( NULL );
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate /*
7647c478bd9Sstevel@tonic-gate * do a reverse lookup on the addr to get the official hostname.
7657c478bd9Sstevel@tonic-gate * this is necessary for kerberos to work right, since the official
7667c478bd9Sstevel@tonic-gate * hostname is used as the kerberos instance.
7677c478bd9Sstevel@tonic-gate */
7687c478bd9Sstevel@tonic-gate #error XXXmcs: need to use DNS callbacks here
769*55fea89dSDan Cross if (( hp = gethostbyaddr((char *) &sin.sin_addr,
7707c478bd9Sstevel@tonic-gate sizeof( sin.sin_addr ), AF_INET)) != NULL ) {
7717c478bd9Sstevel@tonic-gate if ( hp->h_name != NULL ) {
7727c478bd9Sstevel@tonic-gate return( nsldapi_strdup( hp->h_name ));
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate return( NULL );
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate #endif /* KERBEROS */
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate /*
7827c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
7837c478bd9Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
7847c478bd9Sstevel@tonic-gate */
7857c478bd9Sstevel@tonic-gate int
7867c478bd9Sstevel@tonic-gate nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb )
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
7937c478bd9Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
7947c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
7957c478bd9Sstevel@tonic-gate return( -1 );
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
8017c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
8027c478bd9Sstevel@tonic-gate if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
8037c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLOUT )) {
8047c478bd9Sstevel@tonic-gate ++iosp->ios_write_count;
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
8077c478bd9Sstevel@tonic-gate if ( !FD_ISSET( sb->sb_sd,
8087c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds )) {
8097c478bd9Sstevel@tonic-gate FD_SET( sb->sb_sd,
8107c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds );
8117c478bd9Sstevel@tonic-gate ++iosp->ios_write_count;
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
8167c478bd9Sstevel@tonic-gate if ( nsldapi_add_to_cb_pollfds( sb,
8177c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
8187c478bd9Sstevel@tonic-gate ++iosp->ios_write_count;
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate } else {
8227c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
8237c478bd9Sstevel@tonic-gate "nsldapi_iostatus_interest_write: unknown I/O type %d\n",
8247c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate return( 0 );
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
8357c478bd9Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
8367c478bd9Sstevel@tonic-gate */
8377c478bd9Sstevel@tonic-gate int
8387c478bd9Sstevel@tonic-gate nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb )
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
8417c478bd9Sstevel@tonic-gate
8427c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
8457c478bd9Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
8467c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
8477c478bd9Sstevel@tonic-gate return( -1 );
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
8537c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
8547c478bd9Sstevel@tonic-gate if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
8557c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLIN )) {
8567c478bd9Sstevel@tonic-gate ++iosp->ios_read_count;
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
8597c478bd9Sstevel@tonic-gate if ( !FD_ISSET( sb->sb_sd,
8607c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds )) {
8617c478bd9Sstevel@tonic-gate FD_SET( sb->sb_sd,
8627c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds );
8637c478bd9Sstevel@tonic-gate ++iosp->ios_read_count;
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
8687c478bd9Sstevel@tonic-gate if ( nsldapi_add_to_cb_pollfds( sb,
8697c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
8707c478bd9Sstevel@tonic-gate ++iosp->ios_read_count;
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate } else {
8737c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
8747c478bd9Sstevel@tonic-gate "nsldapi_iostatus_interest_read: unknown I/O type %d\n",
8757c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate return( 0 );
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate /*
8857c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
8867c478bd9Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
8877c478bd9Sstevel@tonic-gate */
8887c478bd9Sstevel@tonic-gate int
8897c478bd9Sstevel@tonic-gate nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb )
8907c478bd9Sstevel@tonic-gate {
8917c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
8927c478bd9Sstevel@tonic-gate
8937c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
8967c478bd9Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
8977c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
8987c478bd9Sstevel@tonic-gate return( -1 );
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
9047c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
9057c478bd9Sstevel@tonic-gate if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
9067c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLOUT )) {
9077c478bd9Sstevel@tonic-gate --iosp->ios_write_count;
9087c478bd9Sstevel@tonic-gate }
9097c478bd9Sstevel@tonic-gate if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
9107c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLIN )) {
9117c478bd9Sstevel@tonic-gate --iosp->ios_read_count;
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
9147c478bd9Sstevel@tonic-gate if ( FD_ISSET( sb->sb_sd,
9157c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds )) {
9167c478bd9Sstevel@tonic-gate FD_CLR( sb->sb_sd,
9177c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds );
9187c478bd9Sstevel@tonic-gate --iosp->ios_write_count;
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate if ( FD_ISSET( sb->sb_sd,
9217c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds )) {
9227c478bd9Sstevel@tonic-gate FD_CLR( sb->sb_sd,
9237c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds );
9247c478bd9Sstevel@tonic-gate --iosp->ios_read_count;
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
9297c478bd9Sstevel@tonic-gate if ( nsldapi_clear_from_cb_pollfds( sb,
9307c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
9317c478bd9Sstevel@tonic-gate --iosp->ios_write_count;
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate if ( nsldapi_clear_from_cb_pollfds( sb,
9347c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
9357c478bd9Sstevel@tonic-gate --iosp->ios_read_count;
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate } else {
9387c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
9397c478bd9Sstevel@tonic-gate "nsldapi_iostatus_interest_clear: unknown I/O type %d\n",
9407c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate return( 0 );
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate /*
9507c478bd9Sstevel@tonic-gate * Return a non-zero value if sb is ready for write.
9517c478bd9Sstevel@tonic-gate */
9527c478bd9Sstevel@tonic-gate int
9537c478bd9Sstevel@tonic-gate nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb )
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate int rc;
9567c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
9597c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
9627c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate * if we are using poll() we do something a little tricky: if
9657c478bd9Sstevel@tonic-gate * any bits in the socket's returned events field other than
9667c478bd9Sstevel@tonic-gate * POLLIN (ready for read) are set, we return true. This
9677c478bd9Sstevel@tonic-gate * is done so we notice when a server closes a connection
9687c478bd9Sstevel@tonic-gate * or when another error occurs. The actual error will be
9697c478bd9Sstevel@tonic-gate * noticed later when we call write() or send().
9707c478bd9Sstevel@tonic-gate */
9717c478bd9Sstevel@tonic-gate rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
9727c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, ~POLLIN );
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
9757c478bd9Sstevel@tonic-gate rc = FD_ISSET( sb->sb_sd,
9767c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_writefds );
9777c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
9807c478bd9Sstevel@tonic-gate rc = nsldapi_find_in_cb_pollfds( sb,
9817c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLIN );
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate } else {
9847c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
9857c478bd9Sstevel@tonic-gate "nsldapi_iostatus_is_write_ready: unknown I/O type %d\n",
9867c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
9877c478bd9Sstevel@tonic-gate rc = 0;
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
9917c478bd9Sstevel@tonic-gate return( rc );
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate * Return a non-zero value if sb is ready for read.
9977c478bd9Sstevel@tonic-gate */
9987c478bd9Sstevel@tonic-gate int
9997c478bd9Sstevel@tonic-gate nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb )
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate int rc;
10027c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
10057c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
10087c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
10097c478bd9Sstevel@tonic-gate /*
10107c478bd9Sstevel@tonic-gate * if we are using poll() we do something a little tricky: if
10117c478bd9Sstevel@tonic-gate * any bits in the socket's returned events field other than
10127c478bd9Sstevel@tonic-gate * POLLOUT (ready for write) are set, we return true. This
10137c478bd9Sstevel@tonic-gate * is done so we notice when a server closes a connection
10147c478bd9Sstevel@tonic-gate * or when another error occurs. The actual error will be
10157c478bd9Sstevel@tonic-gate * noticed later when we call read() or recv().
10167c478bd9Sstevel@tonic-gate */
10177c478bd9Sstevel@tonic-gate rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
10187c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, ~POLLOUT );
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
10217c478bd9Sstevel@tonic-gate rc = FD_ISSET( sb->sb_sd,
10227c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_readfds );
10237c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
10267c478bd9Sstevel@tonic-gate rc = nsldapi_find_in_cb_pollfds( sb,
10277c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLOUT );
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate } else {
10307c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
10317c478bd9Sstevel@tonic-gate "nsldapi_iostatus_is_read_ready: unknown I/O type %d\n",
10327c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
10337c478bd9Sstevel@tonic-gate rc = 0;
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
10377c478bd9Sstevel@tonic-gate return( rc );
10387c478bd9Sstevel@tonic-gate }
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate /*
10427c478bd9Sstevel@tonic-gate * Allocated and initialize ld->ld_iostatus if not already done.
10437c478bd9Sstevel@tonic-gate * Should be called with LDAP_IOSTATUS_LOCK locked.
10447c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not (sets error in ld)
10457c478bd9Sstevel@tonic-gate */
10467c478bd9Sstevel@tonic-gate static int
10477c478bd9Sstevel@tonic-gate nsldapi_iostatus_init_nolock( LDAP *ld )
10487c478bd9Sstevel@tonic-gate {
10497c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate if ( ld->ld_iostatus != NULL ) {
10527c478bd9Sstevel@tonic-gate return( 0 );
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate if (( iosp = (NSLDAPIIOStatus *)NSLDAPI_CALLOC( 1,
10567c478bd9Sstevel@tonic-gate sizeof( NSLDAPIIOStatus ))) == NULL ) {
10577c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
10587c478bd9Sstevel@tonic-gate return( -1 );
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate if ( ld->ld_extpoll_fn == NULL ) {
10627c478bd9Sstevel@tonic-gate iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_OSNATIVE;
10637c478bd9Sstevel@tonic-gate #ifndef NSLDAPI_HAVE_POLL
10647c478bd9Sstevel@tonic-gate FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_readfds );
10657c478bd9Sstevel@tonic-gate FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_writefds );
10667c478bd9Sstevel@tonic-gate #endif /* !NSLDAPI_HAVE_POLL */
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate } else {
10697c478bd9Sstevel@tonic-gate iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_CALLBACK;
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate ld->ld_iostatus = iosp;
10737c478bd9Sstevel@tonic-gate return( 0 );
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate void
10787c478bd9Sstevel@tonic-gate nsldapi_iostatus_free( LDAP *ld )
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate if ( ld == NULL ) {
10817c478bd9Sstevel@tonic-gate return;
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate
1084*55fea89dSDan Cross
10857c478bd9Sstevel@tonic-gate /* clean up classic I/O compatibility glue */
10867c478bd9Sstevel@tonic-gate if ( ld->ld_io_fns_ptr != NULL ) {
10877c478bd9Sstevel@tonic-gate if ( ld->ld_ext_session_arg != NULL ) {
10887c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ld->ld_ext_session_arg );
10897c478bd9Sstevel@tonic-gate }
10907c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ld->ld_io_fns_ptr );
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate /* clean up I/O status tracking info. */
10947c478bd9Sstevel@tonic-gate if ( ld->ld_iostatus != NULL ) {
10957c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp = ld->ld_iostatus;
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
10987c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
10997c478bd9Sstevel@tonic-gate if ( iosp->ios_status.ios_osinfo.ossi_pollfds
11007c478bd9Sstevel@tonic-gate != NULL ) {
11017c478bd9Sstevel@tonic-gate NSLDAPI_FREE(
11027c478bd9Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_pollfds );
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
11057c478bd9Sstevel@tonic-gate
11067c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
11077c478bd9Sstevel@tonic-gate if ( iosp->ios_status.ios_cbinfo.cbsi_pollfds
11087c478bd9Sstevel@tonic-gate != NULL ) {
11097c478bd9Sstevel@tonic-gate NSLDAPI_FREE(
11107c478bd9Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds );
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate } else {
11137c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
11147c478bd9Sstevel@tonic-gate "nsldapi_iostatus_free: unknown I/O type %d\n",
11157c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
11167c478bd9Sstevel@tonic-gate }
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate NSLDAPI_FREE( iosp );
11197c478bd9Sstevel@tonic-gate }
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate static int
11247c478bd9Sstevel@tonic-gate nsldapi_get_select_table_size( void )
11257c478bd9Sstevel@tonic-gate {
11267c478bd9Sstevel@tonic-gate static int tblsize = 0; /* static */
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate if ( tblsize == 0 ) {
11297c478bd9Sstevel@tonic-gate #if defined(_WINDOWS) || defined(XP_OS2)
11307c478bd9Sstevel@tonic-gate tblsize = FOPEN_MAX; /* ANSI spec. */
11317c478bd9Sstevel@tonic-gate #else
11327c478bd9Sstevel@tonic-gate #ifdef USE_SYSCONF
11337c478bd9Sstevel@tonic-gate tblsize = sysconf( _SC_OPEN_MAX );
11347c478bd9Sstevel@tonic-gate #else /* USE_SYSCONF */
11357c478bd9Sstevel@tonic-gate tblsize = getdtablesize();
11367c478bd9Sstevel@tonic-gate #endif /* else USE_SYSCONF */
11377c478bd9Sstevel@tonic-gate #endif /* else _WINDOWS */
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate if ( tblsize >= FD_SETSIZE ) {
11407c478bd9Sstevel@tonic-gate /*
11417c478bd9Sstevel@tonic-gate * clamp value so we don't overrun the fd_set structure
11427c478bd9Sstevel@tonic-gate */
11437c478bd9Sstevel@tonic-gate tblsize = FD_SETSIZE - 1;
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate }
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate return( tblsize );
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate static int
11517c478bd9Sstevel@tonic-gate nsldapi_tv2ms( struct timeval *tv )
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate if ( tv == NULL ) {
11547c478bd9Sstevel@tonic-gate return( -1 ); /* infinite timout for poll() */
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate return( tv->tv_sec * 1000 + tv->tv_usec / 1000 );
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate int
11627c478bd9Sstevel@tonic-gate nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout )
11637c478bd9Sstevel@tonic-gate {
11647c478bd9Sstevel@tonic-gate int rc;
11657c478bd9Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_iostatus_poll\n", 0, 0, 0 );
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
11707c478bd9Sstevel@tonic-gate iosp = ld->ld_iostatus;
11717c478bd9Sstevel@tonic-gate
11727c478bd9Sstevel@tonic-gate if ( iosp == NULL ||
11737c478bd9Sstevel@tonic-gate ( iosp->ios_read_count <= 0 && iosp->ios_read_count <= 0 )) {
11747c478bd9Sstevel@tonic-gate rc = 0; /* simulate a timeout */
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
11777c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate rc = NSLDAPI_POLL( iosp->ios_status.ios_osinfo.ossi_pollfds,
11807c478bd9Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_pollfds_size,
11817c478bd9Sstevel@tonic-gate nsldapi_tv2ms( timeout ));
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
11847c478bd9Sstevel@tonic-gate
11857c478bd9Sstevel@tonic-gate /* two (potentially large) struct copies */
11867c478bd9Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_use_readfds
11877c478bd9Sstevel@tonic-gate = iosp->ios_status.ios_osinfo.ossi_readfds;
11887c478bd9Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_use_writefds
11897c478bd9Sstevel@tonic-gate = iosp->ios_status.ios_osinfo.ossi_writefds;
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate #ifdef HPUX9
11927c478bd9Sstevel@tonic-gate rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
11937c478bd9Sstevel@tonic-gate (int *)&iosp->ios_status.ios_osinfo.ossi_use_readfds
11947c478bd9Sstevel@tonic-gate (int *)&iosp->ios_status.ios_osinfo.ossi_use_writefds,
11957c478bd9Sstevel@tonic-gate NULL, timeout );
11967c478bd9Sstevel@tonic-gate #else
11977c478bd9Sstevel@tonic-gate rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
11987c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_readfds,
11997c478bd9Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_writefds,
12007c478bd9Sstevel@tonic-gate NULL, timeout );
12017c478bd9Sstevel@tonic-gate #endif /* else HPUX9 */
12027c478bd9Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
12057c478bd9Sstevel@tonic-gate /*
12067c478bd9Sstevel@tonic-gate * We always pass the session extended I/O argument to
12077c478bd9Sstevel@tonic-gate * the extended poll() callback.
12087c478bd9Sstevel@tonic-gate */
1209*55fea89dSDan Cross rc = ld->ld_extpoll_fn(
12107c478bd9Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds,
12117c478bd9Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds_size,
12127c478bd9Sstevel@tonic-gate nsldapi_tv2ms( timeout ), ld->ld_ext_session_arg );
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate } else {
12157c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
12167c478bd9Sstevel@tonic-gate "nsldapi_iostatus_poll: unknown I/O type %d\n",
12177c478bd9Sstevel@tonic-gate iosp->ios_type, 0, 0 );
12187c478bd9Sstevel@tonic-gate rc = 0; /* simulate a timeout (what else to do?) */
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
12227c478bd9Sstevel@tonic-gate return( rc );
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
12277c478bd9Sstevel@tonic-gate /*
12287c478bd9Sstevel@tonic-gate * returns 1 if "fd" was added to pollfds.
12297c478bd9Sstevel@tonic-gate * returns 1 if some of the bits in "events" were added to pollfds.
12307c478bd9Sstevel@tonic-gate * returns 0 if no changes were made.
12317c478bd9Sstevel@tonic-gate */
12327c478bd9Sstevel@tonic-gate static int
12337c478bd9Sstevel@tonic-gate nsldapi_add_to_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
12347c478bd9Sstevel@tonic-gate short events )
12357c478bd9Sstevel@tonic-gate {
12367c478bd9Sstevel@tonic-gate int i, openslot;
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate /* first we check to see if "fd" is already in our pollfds */
12397c478bd9Sstevel@tonic-gate openslot = -1;
12407c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
12417c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].fd == fd ) {
12427c478bd9Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].events & events )
12437c478bd9Sstevel@tonic-gate != events ) {
12447c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ i ].events |= events;
12457c478bd9Sstevel@tonic-gate return( 1 );
12467c478bd9Sstevel@tonic-gate } else {
12477c478bd9Sstevel@tonic-gate return( 0 );
12487c478bd9Sstevel@tonic-gate }
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].fd == -1 && openslot == -1 ) {
12517c478bd9Sstevel@tonic-gate openslot = i; /* remember for later */
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate /*
12567c478bd9Sstevel@tonic-gate * "fd" is not currently being poll'd on -- add to array.
12577c478bd9Sstevel@tonic-gate * if we need to expand the pollfds array, we do it in increments of
12587c478bd9Sstevel@tonic-gate * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
12597c478bd9Sstevel@tonic-gate */
12607c478bd9Sstevel@tonic-gate if ( openslot == -1 ) {
12617c478bd9Sstevel@tonic-gate struct pollfd *newpollfds;
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds_size == 0 ) {
12647c478bd9Sstevel@tonic-gate newpollfds = (struct pollfd *)NSLDAPI_MALLOC(
12657c478bd9Sstevel@tonic-gate NSLDAPI_POLL_ARRAY_GROWTH
12667c478bd9Sstevel@tonic-gate * sizeof( struct pollfd ));
12677c478bd9Sstevel@tonic-gate } else {
12687c478bd9Sstevel@tonic-gate newpollfds = (struct pollfd *)NSLDAPI_REALLOC(
12697c478bd9Sstevel@tonic-gate pip->ossi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
12707c478bd9Sstevel@tonic-gate + pip->ossi_pollfds_size)
12717c478bd9Sstevel@tonic-gate * sizeof( struct pollfd ));
12727c478bd9Sstevel@tonic-gate }
12737c478bd9Sstevel@tonic-gate if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
12747c478bd9Sstevel@tonic-gate return( 0 );
12757c478bd9Sstevel@tonic-gate }
12767c478bd9Sstevel@tonic-gate pip->ossi_pollfds = newpollfds;
12777c478bd9Sstevel@tonic-gate openslot = pip->ossi_pollfds_size;
12787c478bd9Sstevel@tonic-gate pip->ossi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
12797c478bd9Sstevel@tonic-gate for ( i = openslot + 1; i < pip->ossi_pollfds_size; ++i ) {
12807c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ i ].fd = -1;
12817c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ i ].events =
12827c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ i ].revents = 0;
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].fd = fd;
12867c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].events = events;
12877c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].revents = 0;
12887c478bd9Sstevel@tonic-gate return( 1 );
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate /*
12937c478bd9Sstevel@tonic-gate * returns 1 if any "events" from "fd" were removed from pollfds
12947c478bd9Sstevel@tonic-gate * returns 0 of "fd" wasn't in pollfds or if events did not overlap.
12957c478bd9Sstevel@tonic-gate */
12967c478bd9Sstevel@tonic-gate static int
12977c478bd9Sstevel@tonic-gate nsldapi_clear_from_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
12987c478bd9Sstevel@tonic-gate short events )
12997c478bd9Sstevel@tonic-gate {
13007c478bd9Sstevel@tonic-gate int i;
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
13037c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds[i].fd == fd ) {
13047c478bd9Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].events & events ) != 0 ) {
13057c478bd9Sstevel@tonic-gate pip->ossi_pollfds[ i ].events &= ~events;
13067c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].events == 0 ) {
13077c478bd9Sstevel@tonic-gate pip->ossi_pollfds[i].fd = -1;
13087c478bd9Sstevel@tonic-gate }
13097c478bd9Sstevel@tonic-gate return( 1 ); /* events overlap */
13107c478bd9Sstevel@tonic-gate } else {
13117c478bd9Sstevel@tonic-gate return( 0 ); /* events do not overlap */
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate }
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate return( 0 ); /* "fd" was not found */
13177c478bd9Sstevel@tonic-gate }
13187c478bd9Sstevel@tonic-gate
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate /*
13217c478bd9Sstevel@tonic-gate * returns 1 if any "revents" from "fd" were set in pollfds revents field.
13227c478bd9Sstevel@tonic-gate * returns 0 if not.
13237c478bd9Sstevel@tonic-gate */
13247c478bd9Sstevel@tonic-gate static int
13257c478bd9Sstevel@tonic-gate nsldapi_find_in_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
13267c478bd9Sstevel@tonic-gate short revents )
13277c478bd9Sstevel@tonic-gate {
13287c478bd9Sstevel@tonic-gate int i;
13297c478bd9Sstevel@tonic-gate
13307c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
13317c478bd9Sstevel@tonic-gate if ( pip->ossi_pollfds[i].fd == fd ) {
13327c478bd9Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].revents & revents ) != 0 ) {
13337c478bd9Sstevel@tonic-gate return( 1 ); /* revents overlap */
13347c478bd9Sstevel@tonic-gate } else {
13357c478bd9Sstevel@tonic-gate return( 0 ); /* revents do not overlap */
13367c478bd9Sstevel@tonic-gate }
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate return( 0 ); /* "fd" was not found */
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate /*
13467c478bd9Sstevel@tonic-gate * returns 1 if "sb" was added to pollfds.
13477c478bd9Sstevel@tonic-gate * returns 1 if some of the bits in "events" were added to pollfds.
13487c478bd9Sstevel@tonic-gate * returns 0 if no changes were made.
13497c478bd9Sstevel@tonic-gate */
13507c478bd9Sstevel@tonic-gate static int
13517c478bd9Sstevel@tonic-gate nsldapi_add_to_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
13527c478bd9Sstevel@tonic-gate short events )
13537c478bd9Sstevel@tonic-gate {
13547c478bd9Sstevel@tonic-gate int i, openslot;
13557c478bd9Sstevel@tonic-gate
13567c478bd9Sstevel@tonic-gate /* first we check to see if "sb" is already in our pollfds */
13577c478bd9Sstevel@tonic-gate openslot = -1;
13587c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
13597c478bd9Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
13607c478bd9Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_events & events )
13617c478bd9Sstevel@tonic-gate != events ) {
13627c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events |= events;
13637c478bd9Sstevel@tonic-gate return( 1 );
13647c478bd9Sstevel@tonic-gate } else {
13657c478bd9Sstevel@tonic-gate return( 0 );
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate }
13687c478bd9Sstevel@tonic-gate if ( pip->cbsi_pollfds[ i ].lpoll_fd == -1 && openslot == -1 ) {
13697c478bd9Sstevel@tonic-gate openslot = i; /* remember for later */
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate * "sb" is not currently being poll'd on -- add to array.
13757c478bd9Sstevel@tonic-gate * if we need to expand the pollfds array, we do it in increments of
13767c478bd9Sstevel@tonic-gate * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
13777c478bd9Sstevel@tonic-gate */
13787c478bd9Sstevel@tonic-gate if ( openslot == -1 ) {
13797c478bd9Sstevel@tonic-gate LDAP_X_PollFD *newpollfds;
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate if ( pip->cbsi_pollfds_size == 0 ) {
13827c478bd9Sstevel@tonic-gate newpollfds = (LDAP_X_PollFD *)NSLDAPI_MALLOC(
13837c478bd9Sstevel@tonic-gate NSLDAPI_POLL_ARRAY_GROWTH
13847c478bd9Sstevel@tonic-gate * sizeof( LDAP_X_PollFD ));
13857c478bd9Sstevel@tonic-gate } else {
13867c478bd9Sstevel@tonic-gate newpollfds = (LDAP_X_PollFD *)NSLDAPI_REALLOC(
13877c478bd9Sstevel@tonic-gate pip->cbsi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
13887c478bd9Sstevel@tonic-gate + pip->cbsi_pollfds_size)
13897c478bd9Sstevel@tonic-gate * sizeof( LDAP_X_PollFD ));
13907c478bd9Sstevel@tonic-gate }
13917c478bd9Sstevel@tonic-gate if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
13927c478bd9Sstevel@tonic-gate return( 0 );
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate pip->cbsi_pollfds = newpollfds;
13957c478bd9Sstevel@tonic-gate openslot = pip->cbsi_pollfds_size;
13967c478bd9Sstevel@tonic-gate pip->cbsi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
13977c478bd9Sstevel@tonic-gate for ( i = openslot + 1; i < pip->cbsi_pollfds_size; ++i ) {
13987c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_fd = -1;
13997c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_socketarg = NULL;
14007c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events =
14017c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_revents = 0;
14027c478bd9Sstevel@tonic-gate }
14037c478bd9Sstevel@tonic-gate }
14047c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_fd = sb->sb_sd;
14057c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_socketarg =
14067c478bd9Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg;
14077c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_events = events;
14087c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_revents = 0;
14097c478bd9Sstevel@tonic-gate return( 1 );
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate /*
14147c478bd9Sstevel@tonic-gate * returns 1 if any "events" from "sb" were removed from pollfds
14157c478bd9Sstevel@tonic-gate * returns 0 of "sb" wasn't in pollfds or if events did not overlap.
14167c478bd9Sstevel@tonic-gate */
14177c478bd9Sstevel@tonic-gate static int
14187c478bd9Sstevel@tonic-gate nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
14197c478bd9Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events )
14207c478bd9Sstevel@tonic-gate {
14217c478bd9Sstevel@tonic-gate int i;
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
14247c478bd9Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
14257c478bd9Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_events
14267c478bd9Sstevel@tonic-gate & events ) != 0 ) {
14277c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events &= ~events;
14287c478bd9Sstevel@tonic-gate if ( pip->cbsi_pollfds[ i ].lpoll_events
14297c478bd9Sstevel@tonic-gate == 0 ) {
14307c478bd9Sstevel@tonic-gate pip->cbsi_pollfds[i].lpoll_fd = -1;
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate return( 1 ); /* events overlap */
14337c478bd9Sstevel@tonic-gate } else {
14347c478bd9Sstevel@tonic-gate return( 0 ); /* events do not overlap */
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate return( 0 ); /* "sb" was not found */
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate
14437c478bd9Sstevel@tonic-gate /*
14447c478bd9Sstevel@tonic-gate * returns 1 if any "revents" from "sb" were set in pollfds revents field.
14457c478bd9Sstevel@tonic-gate * returns 0 if not.
14467c478bd9Sstevel@tonic-gate */
14477c478bd9Sstevel@tonic-gate static int
14487c478bd9Sstevel@tonic-gate nsldapi_find_in_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
14497c478bd9Sstevel@tonic-gate short revents )
14507c478bd9Sstevel@tonic-gate {
14517c478bd9Sstevel@tonic-gate int i;
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
14547c478bd9Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
14557c478bd9Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_revents
14567c478bd9Sstevel@tonic-gate & revents ) != 0 ) {
14577c478bd9Sstevel@tonic-gate return( 1 ); /* revents overlap */
14587c478bd9Sstevel@tonic-gate } else {
14597c478bd9Sstevel@tonic-gate return( 0 ); /* revents do not overlap */
14607c478bd9Sstevel@tonic-gate }
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate
14647c478bd9Sstevel@tonic-gate return( 0 ); /* "sb" was not found */
14657c478bd9Sstevel@tonic-gate }
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate
14687c478bd9Sstevel@tonic-gate /*
14697c478bd9Sstevel@tonic-gate * Install read and write functions into lber layer / sb
14707c478bd9Sstevel@tonic-gate */
14717c478bd9Sstevel@tonic-gate int
14727c478bd9Sstevel@tonic-gate nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb )
14737c478bd9Sstevel@tonic-gate {
14747c478bd9Sstevel@tonic-gate struct lber_x_ext_io_fns lberiofns;
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate memset( &lberiofns, 0, sizeof(struct lber_x_ext_io_fns) );
14777c478bd9Sstevel@tonic-gate if ( NULL != sb ) {
14787c478bd9Sstevel@tonic-gate lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
14797c478bd9Sstevel@tonic-gate lberiofns.lbextiofn_read = ld->ld_extread_fn;
14807c478bd9Sstevel@tonic-gate lberiofns.lbextiofn_write = ld->ld_extwrite_fn;
14817c478bd9Sstevel@tonic-gate lberiofns.lbextiofn_writev = ld->ld_extwritev_fn;
14827c478bd9Sstevel@tonic-gate lberiofns.lbextiofn_socket_arg = ld->ld_ext_session_arg;
14837c478bd9Sstevel@tonic-gate
14847c478bd9Sstevel@tonic-gate if ( ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS,
14857c478bd9Sstevel@tonic-gate &lberiofns ) != 0 ) {
14867c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
14877c478bd9Sstevel@tonic-gate }
14887c478bd9Sstevel@tonic-gate }
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
14917c478bd9Sstevel@tonic-gate }
14927c478bd9Sstevel@tonic-gate
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate /*
14957c478bd9Sstevel@tonic-gate ******************************************************************************
14967c478bd9Sstevel@tonic-gate * One struct and several functions to bridge the gap between new extended
14977c478bd9Sstevel@tonic-gate * I/O functions that are installed using ldap_set_option( ...,
14987c478bd9Sstevel@tonic-gate * LDAP_OPT_EXTIO_FN_PTRS, ... ) and the original "classic" I/O functions
14997c478bd9Sstevel@tonic-gate * (installed using LDAP_OPT_IO_FN_PTRS) follow.
15007c478bd9Sstevel@tonic-gate *
15017c478bd9Sstevel@tonic-gate * Our basic strategy is to use the new extended arg to hold a pointer to a
15027c478bd9Sstevel@tonic-gate * structure that contains a pointer to the LDAP * (which contains pointers
15037c478bd9Sstevel@tonic-gate * to the old functions so we can call them) as well as a pointer to an
15047c478bd9Sstevel@tonic-gate * LBER_SOCKET to hold the socket used by the classic functions (the new
15057c478bd9Sstevel@tonic-gate * functions use a simple int for the socket).
15067c478bd9Sstevel@tonic-gate */
15077c478bd9Sstevel@tonic-gate typedef struct nsldapi_compat_socket_info {
15087c478bd9Sstevel@tonic-gate LBER_SOCKET csi_socket;
15097c478bd9Sstevel@tonic-gate LDAP *csi_ld;
15107c478bd9Sstevel@tonic-gate } NSLDAPICompatSocketInfo;
1511*55fea89dSDan Cross
15127c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
15137c478bd9Sstevel@tonic-gate nsldapi_ext_compat_read( int s, void *buf, int len,
15147c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg )
15157c478bd9Sstevel@tonic-gate {
15167c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
15177c478bd9Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate return( iofns->liof_read( csip->csi_socket, buf, len ));
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate
15237c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
15247c478bd9Sstevel@tonic-gate nsldapi_ext_compat_write( int s, const void *buf, int len,
15257c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg )
15267c478bd9Sstevel@tonic-gate {
15277c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
15287c478bd9Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate return( iofns->liof_write( csip->csi_socket, buf, len ));
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
15357c478bd9Sstevel@tonic-gate nsldapi_ext_compat_poll( LDAP_X_PollFD fds[], int nfds, int timeout,
15367c478bd9Sstevel@tonic-gate struct lextiof_session_private *arg )
15377c478bd9Sstevel@tonic-gate {
15387c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
15397c478bd9Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
15407c478bd9Sstevel@tonic-gate fd_set readfds, writefds;
15417c478bd9Sstevel@tonic-gate int i, rc, maxfd = 0;
15427c478bd9Sstevel@tonic-gate struct timeval tv, *tvp;
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate /*
15457c478bd9Sstevel@tonic-gate * Prepare fd_sets for select()
15467c478bd9Sstevel@tonic-gate */
15477c478bd9Sstevel@tonic-gate FD_ZERO( &readfds );
15487c478bd9Sstevel@tonic-gate FD_ZERO( &writefds );
15497c478bd9Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) {
15507c478bd9Sstevel@tonic-gate if ( fds[ i ].lpoll_fd < 0 ) {
15517c478bd9Sstevel@tonic-gate continue;
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate if ( fds[ i ].lpoll_fd >= FD_SETSIZE ) {
15557c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO( csip->csi_ld, EINVAL );
15567c478bd9Sstevel@tonic-gate return( -1 );
15577c478bd9Sstevel@tonic-gate }
1558*55fea89dSDan Cross
15597c478bd9Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )) {
15607c478bd9Sstevel@tonic-gate FD_SET( fds[i].lpoll_fd, &readfds );
15617c478bd9Sstevel@tonic-gate }
15627c478bd9Sstevel@tonic-gate
15637c478bd9Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )) {
15647c478bd9Sstevel@tonic-gate FD_SET( fds[i].lpoll_fd, &writefds );
15657c478bd9Sstevel@tonic-gate }
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate fds[i].lpoll_revents = 0; /* clear revents */
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate if ( fds[i].lpoll_fd >= maxfd ) {
15707c478bd9Sstevel@tonic-gate maxfd = fds[i].lpoll_fd;
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate }
15737c478bd9Sstevel@tonic-gate
15747c478bd9Sstevel@tonic-gate /*
15757c478bd9Sstevel@tonic-gate * select() using callback.
15767c478bd9Sstevel@tonic-gate */
15777c478bd9Sstevel@tonic-gate ++maxfd;
15787c478bd9Sstevel@tonic-gate if ( timeout == -1 ) {
15797c478bd9Sstevel@tonic-gate tvp = NULL;
15807c478bd9Sstevel@tonic-gate } else {
15817c478bd9Sstevel@tonic-gate tv.tv_sec = timeout / 1000;
15827c478bd9Sstevel@tonic-gate tv.tv_usec = 1000 * ( timeout - tv.tv_sec * 1000 );
15837c478bd9Sstevel@tonic-gate tvp = &tv;
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate rc = iofns->liof_select( maxfd, &readfds, &writefds, NULL, tvp );
15867c478bd9Sstevel@tonic-gate if ( rc <= 0 ) { /* timeout or fatal error */
15877c478bd9Sstevel@tonic-gate return( rc );
15887c478bd9Sstevel@tonic-gate }
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate /*
15917c478bd9Sstevel@tonic-gate * Use info. in fd_sets to populate poll() revents.
15927c478bd9Sstevel@tonic-gate */
15937c478bd9Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) {
15947c478bd9Sstevel@tonic-gate if ( fds[ i ].lpoll_fd < 0 ) {
15957c478bd9Sstevel@tonic-gate continue;
15967c478bd9Sstevel@tonic-gate }
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )
15997c478bd9Sstevel@tonic-gate && FD_ISSET( fds[i].lpoll_fd, &readfds )) {
16007c478bd9Sstevel@tonic-gate fds[i].lpoll_revents |= LDAP_X_POLLIN;
16017c478bd9Sstevel@tonic-gate }
16027c478bd9Sstevel@tonic-gate
16037c478bd9Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )
16047c478bd9Sstevel@tonic-gate && FD_ISSET( fds[i].lpoll_fd, &writefds )) {
16057c478bd9Sstevel@tonic-gate fds[i].lpoll_revents |= LDAP_X_POLLOUT;
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate /* XXXmcs: any other cases to deal with? LDAP_X_POLLERR? */
16097c478bd9Sstevel@tonic-gate }
16107c478bd9Sstevel@tonic-gate
16117c478bd9Sstevel@tonic-gate return( rc );
16127c478bd9Sstevel@tonic-gate }
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate
16157c478bd9Sstevel@tonic-gate static LBER_SOCKET
16167c478bd9Sstevel@tonic-gate nsldapi_compat_socket( LDAP *ld, int secure, int domain, int type,
16177c478bd9Sstevel@tonic-gate int protocol )
16187c478bd9Sstevel@tonic-gate {
16197c478bd9Sstevel@tonic-gate int s;
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate s = ld->ld_io_fns_ptr->liof_socket( domain, type, protocol );
16227c478bd9Sstevel@tonic-gate
16237c478bd9Sstevel@tonic-gate if ( s >= 0 ) {
16247c478bd9Sstevel@tonic-gate char *errmsg = NULL;
16257c478bd9Sstevel@tonic-gate
16267c478bd9Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
16277c478bd9Sstevel@tonic-gate if ( ld->ld_io_fns_ptr->liof_select != NULL
16287c478bd9Sstevel@tonic-gate && s >= FD_SETSIZE ) {
16297c478bd9Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN,
16307c478bd9Sstevel@tonic-gate "can't use socket >= FD_SETSIZE");
16317c478bd9Sstevel@tonic-gate }
16327c478bd9Sstevel@tonic-gate #elif !defined(_WINDOWS) /* not on Windows and do not have poll() */
16337c478bd9Sstevel@tonic-gate if ( s >= FD_SETSIZE ) {
16347c478bd9Sstevel@tonic-gate errmsg = "can't use socket >= FD_SETSIZE";
16357c478bd9Sstevel@tonic-gate }
16367c478bd9Sstevel@tonic-gate #endif
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate if ( NULL == errmsg && secure &&
16397c478bd9Sstevel@tonic-gate ld->ld_io_fns_ptr->liof_ssl_enable( s ) < 0 ) {
16407c478bd9Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN,
16417c478bd9Sstevel@tonic-gate "failed to enable secure mode");
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate if ( NULL != errmsg ) {
16457c478bd9Sstevel@tonic-gate if ( NULL == ld->ld_io_fns_ptr->liof_close ) {
16467c478bd9Sstevel@tonic-gate nsldapi_os_closesocket( s );
16477c478bd9Sstevel@tonic-gate } else {
16487c478bd9Sstevel@tonic-gate ld->ld_io_fns_ptr->liof_close( s );
16497c478bd9Sstevel@tonic-gate }
16507c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
16517c478bd9Sstevel@tonic-gate nsldapi_strdup( errmsg ));
16527c478bd9Sstevel@tonic-gate return( -1 );
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate }
16557c478bd9Sstevel@tonic-gate
16567c478bd9Sstevel@tonic-gate return( s );
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate /*
16617c478bd9Sstevel@tonic-gate * Note: timeout is ignored because we have no way to pass it via
16627c478bd9Sstevel@tonic-gate * the old I/O callback interface.
16637c478bd9Sstevel@tonic-gate */
16647c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
16657c478bd9Sstevel@tonic-gate nsldapi_ext_compat_connect( const char *hostlist, int defport, int timeout,
16667c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg,
16677c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp
16687c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
16697c478bd9Sstevel@tonic-gate , void **not_used )
16707c478bd9Sstevel@tonic-gate #else
16717c478bd9Sstevel@tonic-gate )
16727c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
16737c478bd9Sstevel@tonic-gate {
16747c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *defcsip;
16757c478bd9Sstevel@tonic-gate struct ldap_io_fns *iofns;
16767c478bd9Sstevel@tonic-gate int s, secure;
16777c478bd9Sstevel@tonic-gate NSLDAPI_SOCKET_FN *socketfn;
16787c478bd9Sstevel@tonic-gate NSLDAPI_IOCTL_FN *ioctlfn;
16797c478bd9Sstevel@tonic-gate NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn;
16807c478bd9Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn;
16817c478bd9Sstevel@tonic-gate NSLDAPI_CLOSE_FN *closefn;
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate defcsip = (NSLDAPICompatSocketInfo *)sessionarg;
16847c478bd9Sstevel@tonic-gate iofns = defcsip->csi_ld->ld_io_fns_ptr;
16857c478bd9Sstevel@tonic-gate
16867c478bd9Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
16877c478bd9Sstevel@tonic-gate if ( NULL == iofns->liof_ssl_enable ) {
16887c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO( defcsip->csi_ld, EINVAL );
16897c478bd9Sstevel@tonic-gate return( -1 );
16907c478bd9Sstevel@tonic-gate }
16917c478bd9Sstevel@tonic-gate secure = 1;
16927c478bd9Sstevel@tonic-gate } else {
16937c478bd9Sstevel@tonic-gate secure = 0;
16947c478bd9Sstevel@tonic-gate }
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate socketfn = ( iofns->liof_socket == NULL ) ?
16977c478bd9Sstevel@tonic-gate nsldapi_os_socket : nsldapi_compat_socket;
16987c478bd9Sstevel@tonic-gate ioctlfn = ( iofns->liof_ioctl == NULL ) ?
16997c478bd9Sstevel@tonic-gate nsldapi_os_ioctl : (NSLDAPI_IOCTL_FN *)(iofns->liof_ioctl);
17007c478bd9Sstevel@tonic-gate if ( NULL == iofns->liof_connect ) {
17017c478bd9Sstevel@tonic-gate connectwithtofn = nsldapi_os_connect_with_to;
17027c478bd9Sstevel@tonic-gate connectfn = NULL;
17037c478bd9Sstevel@tonic-gate } else {
17047c478bd9Sstevel@tonic-gate connectwithtofn = NULL;
17057c478bd9Sstevel@tonic-gate connectfn = iofns->liof_connect;
17067c478bd9Sstevel@tonic-gate }
17077c478bd9Sstevel@tonic-gate closefn = ( iofns->liof_close == NULL ) ?
1708*55fea89dSDan Cross nsldapi_os_closesocket : iofns->liof_close;
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate s = nsldapi_try_each_host( defcsip->csi_ld, hostlist, defport,
17117c478bd9Sstevel@tonic-gate secure, socketfn, ioctlfn, connectwithtofn,
17127c478bd9Sstevel@tonic-gate connectfn, closefn );
17137c478bd9Sstevel@tonic-gate
17147c478bd9Sstevel@tonic-gate if ( s >= 0 ) {
17157c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip;
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate if (( csip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
17187c478bd9Sstevel@tonic-gate sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
17197c478bd9Sstevel@tonic-gate (*closefn)( s );
17207c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( defcsip->csi_ld, LDAP_NO_MEMORY,
17217c478bd9Sstevel@tonic-gate NULL, NULL );
17227c478bd9Sstevel@tonic-gate return( -1 );
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate csip->csi_socket = s;
17267c478bd9Sstevel@tonic-gate csip->csi_ld = defcsip->csi_ld;
17277c478bd9Sstevel@tonic-gate *socketargp = (void *)csip;
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate /*
17307c478bd9Sstevel@tonic-gate * We always return 1, which is a valid but not unique socket
17317c478bd9Sstevel@tonic-gate * (file descriptor) number. The extended I/O functions only
17327c478bd9Sstevel@tonic-gate * require that the combination of the void *arg and the int
17337c478bd9Sstevel@tonic-gate * socket be unique. Since we allocate the
17347c478bd9Sstevel@tonic-gate * NSLDAPICompatSocketInfo that we assign to arg, we meet
17357c478bd9Sstevel@tonic-gate * that requirement.
17367c478bd9Sstevel@tonic-gate */
17377c478bd9Sstevel@tonic-gate s = 1;
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate return( s );
17417c478bd9Sstevel@tonic-gate }
17427c478bd9Sstevel@tonic-gate
17437c478bd9Sstevel@tonic-gate
17447c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
17457c478bd9Sstevel@tonic-gate nsldapi_ext_compat_close( int s, struct lextiof_socket_private *arg )
17467c478bd9Sstevel@tonic-gate {
17477c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
17487c478bd9Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
17497c478bd9Sstevel@tonic-gate int rc;
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate rc = iofns->liof_close( csip->csi_socket );
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate NSLDAPI_FREE( csip );
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate return( rc );
17567c478bd9Sstevel@tonic-gate }
17577c478bd9Sstevel@tonic-gate
17587c478bd9Sstevel@tonic-gate /*
17597c478bd9Sstevel@tonic-gate * Install the I/O functions.
17607c478bd9Sstevel@tonic-gate * Return an LDAP error code (LDAP_SUCCESS if all goes well).
17617c478bd9Sstevel@tonic-gate */
17627c478bd9Sstevel@tonic-gate int
17637c478bd9Sstevel@tonic-gate nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns )
17647c478bd9Sstevel@tonic-gate {
17657c478bd9Sstevel@tonic-gate NSLDAPICompatSocketInfo *defcsip;
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate if (( defcsip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
17687c478bd9Sstevel@tonic-gate sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
17697c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY );
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate
17727c478bd9Sstevel@tonic-gate defcsip->csi_socket = -1;
17737c478bd9Sstevel@tonic-gate defcsip->csi_ld = ld;
17747c478bd9Sstevel@tonic-gate
17757c478bd9Sstevel@tonic-gate if ( ld->ld_io_fns_ptr != NULL ) {
17767c478bd9Sstevel@tonic-gate (void)memset( (char *)ld->ld_io_fns_ptr, 0,
17777c478bd9Sstevel@tonic-gate sizeof( struct ldap_io_fns ));
17787c478bd9Sstevel@tonic-gate } else if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_CALLOC(
17797c478bd9Sstevel@tonic-gate 1, sizeof( struct ldap_io_fns ))) == NULL ) {
17807c478bd9Sstevel@tonic-gate NSLDAPI_FREE( defcsip );
17817c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY );
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate
17847c478bd9Sstevel@tonic-gate /* struct copy */
17857c478bd9Sstevel@tonic-gate *(ld->ld_io_fns_ptr) = *iofns;
17867c478bd9Sstevel@tonic-gate
17877c478bd9Sstevel@tonic-gate ld->ld_extio_size = LBER_X_EXTIO_FNS_SIZE;
17887c478bd9Sstevel@tonic-gate ld->ld_ext_session_arg = defcsip;
17897c478bd9Sstevel@tonic-gate ld->ld_extread_fn = nsldapi_ext_compat_read;
17907c478bd9Sstevel@tonic-gate ld->ld_extwrite_fn = nsldapi_ext_compat_write;
17917c478bd9Sstevel@tonic-gate ld->ld_extpoll_fn = nsldapi_ext_compat_poll;
17927c478bd9Sstevel@tonic-gate ld->ld_extconnect_fn = nsldapi_ext_compat_connect;
17937c478bd9Sstevel@tonic-gate ld->ld_extclose_fn = nsldapi_ext_compat_close;
17947c478bd9Sstevel@tonic-gate
17957c478bd9Sstevel@tonic-gate return( nsldapi_install_lber_extiofns( ld, ld->ld_sbp ));
17967c478bd9Sstevel@tonic-gate }
17977c478bd9Sstevel@tonic-gate /*
17987c478bd9Sstevel@tonic-gate * end of compat I/O functions
17997c478bd9Sstevel@tonic-gate ******************************************************************************
18007c478bd9Sstevel@tonic-gate */
18017c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
18027c478bd9Sstevel@tonic-gate /*
18037c478bd9Sstevel@tonic-gate * _ns_gethostbyaddr is a helper function for the ssl layer so that
18047c478bd9Sstevel@tonic-gate * it can use the ldap layer's gethostbyaddr resolver.
18057c478bd9Sstevel@tonic-gate */
18067c478bd9Sstevel@tonic-gate
18077c478bd9Sstevel@tonic-gate LDAPHostEnt *
18087c478bd9Sstevel@tonic-gate _ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type,
18097c478bd9Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
18107c478bd9Sstevel@tonic-gate void *extradata)
18117c478bd9Sstevel@tonic-gate {
18127c478bd9Sstevel@tonic-gate if (ld == NULL || ld->ld_dns_gethostbyaddr_fn == NULL)
18137c478bd9Sstevel@tonic-gate return (NULL);
18147c478bd9Sstevel@tonic-gate return (ld->ld_dns_gethostbyaddr_fn(addr, length, type,
18157c478bd9Sstevel@tonic-gate result, buffer, buflen, statusp, extradata));
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate
1821