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 367c478bd9Sstevel@tonic-gate #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 547c478bd9Sstevel@tonic-gate #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 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 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 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(); 318*19449258SJosef '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"); 3597c478bd9Sstevel@tonic-gate 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 6687c478bd9Sstevel@tonic-gate 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 7697c478bd9Sstevel@tonic-gate 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 10847c478bd9Sstevel@tonic-gate 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 */ 12097c478bd9Sstevel@tonic-gate 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; 15117c478bd9Sstevel@tonic-gate 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 } 15587c478bd9Sstevel@tonic-gate 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 ) ? 17087c478bd9Sstevel@tonic-gate 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