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