1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3*0Sstevel@tonic-gate * Use is subject to license terms.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate /*
9*0Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
10*0Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
11*0Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
12*0Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
15*0Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16*0Sstevel@tonic-gate * implied. See the License for the specific language governing
17*0Sstevel@tonic-gate * rights and limitations under the License.
18*0Sstevel@tonic-gate *
19*0Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
20*0Sstevel@tonic-gate * March 31, 1998.
21*0Sstevel@tonic-gate *
22*0Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
23*0Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
24*0Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25*0Sstevel@tonic-gate * Rights Reserved.
26*0Sstevel@tonic-gate *
27*0Sstevel@tonic-gate * Contributor(s):
28*0Sstevel@tonic-gate */
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * Copyright (c) 1995 Regents of the University of Michigan.
31*0Sstevel@tonic-gate * All rights reserved.
32*0Sstevel@tonic-gate */
33*0Sstevel@tonic-gate /*
34*0Sstevel@tonic-gate * os-ip.c -- platform-specific TCP & UDP related code
35*0Sstevel@tonic-gate */
36*0Sstevel@tonic-gate
37*0Sstevel@tonic-gate #if 0
38*0Sstevel@tonic-gate #ifndef lint
39*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
40*0Sstevel@tonic-gate #endif
41*0Sstevel@tonic-gate #endif
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gate #include "ldap-int.h"
44*0Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
45*0Sstevel@tonic-gate #include <signal.h>
46*0Sstevel@tonic-gate #endif
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
49*0Sstevel@tonic-gate #include <poll.h>
50*0Sstevel@tonic-gate #endif
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate #ifdef _WINDOWS
54*0Sstevel@tonic-gate #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) == INVALID_SOCKET)
55*0Sstevel@tonic-gate #else
56*0Sstevel@tonic-gate #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) < 0 )
57*0Sstevel@tonic-gate #endif
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate #define NSLDAPI_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate /*
64*0Sstevel@tonic-gate * Structures and union for tracking status of network sockets
65*0Sstevel@tonic-gate */
66*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
67*0Sstevel@tonic-gate struct nsldapi_os_statusinfo { /* used with native OS poll() */
68*0Sstevel@tonic-gate struct pollfd *ossi_pollfds;
69*0Sstevel@tonic-gate int ossi_pollfds_size;
70*0Sstevel@tonic-gate };
71*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
72*0Sstevel@tonic-gate struct nsldapi_os_statusinfo { /* used with native OS select() */
73*0Sstevel@tonic-gate fd_set ossi_readfds;
74*0Sstevel@tonic-gate fd_set ossi_writefds;
75*0Sstevel@tonic-gate fd_set ossi_use_readfds;
76*0Sstevel@tonic-gate fd_set ossi_use_writefds;
77*0Sstevel@tonic-gate };
78*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo { /* used with ext. I/O poll() callback */
81*0Sstevel@tonic-gate LDAP_X_PollFD *cbsi_pollfds;
82*0Sstevel@tonic-gate int cbsi_pollfds_size;
83*0Sstevel@tonic-gate };
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate /*
86*0Sstevel@tonic-gate * NSLDAPI_CB_POLL_MATCH() evaluates to non-zero (true) if the Sockbuf *sdp
87*0Sstevel@tonic-gate * matches the LDAP_X_PollFD pollfd.
88*0Sstevel@tonic-gate */
89*0Sstevel@tonic-gate #ifdef _WINDOWS
90*0Sstevel@tonic-gate #define NSLDAPI_CB_POLL_SD_CAST (unsigned int)
91*0Sstevel@tonic-gate #else
92*0Sstevel@tonic-gate #define NSLDAPI_CB_POLL_SD_CAST
93*0Sstevel@tonic-gate #endif
94*0Sstevel@tonic-gate #if defined(LDAP_SASLIO_HOOKS)
95*0Sstevel@tonic-gate #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
96*0Sstevel@tonic-gate ( ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd)) && \
97*0Sstevel@tonic-gate (((sbp)->sb_sasl_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) || \
98*0Sstevel@tonic-gate ((sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) ) )
99*0Sstevel@tonic-gate #else
100*0Sstevel@tonic-gate #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
101*0Sstevel@tonic-gate ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd) && \
102*0Sstevel@tonic-gate (sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg)
103*0Sstevel@tonic-gate #endif
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gate struct nsldapi_iostatus_info {
107*0Sstevel@tonic-gate int ios_type;
108*0Sstevel@tonic-gate #define NSLDAPI_IOSTATUS_TYPE_OSNATIVE 1 /* poll() or select() */
109*0Sstevel@tonic-gate #define NSLDAPI_IOSTATUS_TYPE_CALLBACK 2 /* poll()-like */
110*0Sstevel@tonic-gate int ios_read_count;
111*0Sstevel@tonic-gate int ios_write_count;
112*0Sstevel@tonic-gate union {
113*0Sstevel@tonic-gate struct nsldapi_os_statusinfo ios_osinfo;
114*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo ios_cbinfo;
115*0Sstevel@tonic-gate } ios_status;
116*0Sstevel@tonic-gate };
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
120*0Sstevel@tonic-gate static int nsldapi_add_to_os_pollfds( int fd,
121*0Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short events );
122*0Sstevel@tonic-gate static int nsldapi_clear_from_os_pollfds( int fd,
123*0Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short events );
124*0Sstevel@tonic-gate static int nsldapi_find_in_os_pollfds( int fd,
125*0Sstevel@tonic-gate struct nsldapi_os_statusinfo *pip, short revents );
126*0Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
127*0Sstevel@tonic-gate
128*0Sstevel@tonic-gate static int nsldapi_iostatus_init_nolock( LDAP *ld );
129*0Sstevel@tonic-gate static int nsldapi_add_to_cb_pollfds( Sockbuf *sb,
130*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events );
131*0Sstevel@tonic-gate static int nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
132*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events );
133*0Sstevel@tonic-gate static int nsldapi_find_in_cb_pollfds( Sockbuf *sb,
134*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short revents );
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate #ifdef irix
138*0Sstevel@tonic-gate #ifndef _PR_THREADS
139*0Sstevel@tonic-gate /*
140*0Sstevel@tonic-gate * XXXmcs: on IRIX NSPR's poll() and select() wrappers will crash if NSPR
141*0Sstevel@tonic-gate * has not been initialized. We work around the problem by bypassing
142*0Sstevel@tonic-gate * the NSPR wrapper functions and going directly to the OS' functions.
143*0Sstevel@tonic-gate */
144*0Sstevel@tonic-gate #define NSLDAPI_POLL _poll
145*0Sstevel@tonic-gate #define NSLDAPI_SELECT _select
146*0Sstevel@tonic-gate extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
147*0Sstevel@tonic-gate extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
148*0Sstevel@tonic-gate fd_set *exceptfds, struct timeval *timeout);
149*0Sstevel@tonic-gate #else /* _PR_THREADS */
150*0Sstevel@tonic-gate #define NSLDAPI_POLL poll
151*0Sstevel@tonic-gate #define NSLDAPI_SELECT select
152*0Sstevel@tonic-gate #endif /* else _PR_THREADS */
153*0Sstevel@tonic-gate #else /* irix */
154*0Sstevel@tonic-gate #define NSLDAPI_POLL poll
155*0Sstevel@tonic-gate #define NSLDAPI_SELECT select
156*0Sstevel@tonic-gate #endif /* else irix */
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate
159*0Sstevel@tonic-gate static LBER_SOCKET nsldapi_os_socket( LDAP *ld, int secure, int domain,
160*0Sstevel@tonic-gate int type, int protocol );
161*0Sstevel@tonic-gate static int nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp );
162*0Sstevel@tonic-gate static int nsldapi_os_connect_with_to( LBER_SOCKET s, struct sockaddr *name,
163*0Sstevel@tonic-gate int namelen, LDAP *ld);
164*0Sstevel@tonic-gate
165*0Sstevel@tonic-gate /*
166*0Sstevel@tonic-gate * Function typedefs used by nsldapi_try_each_host()
167*0Sstevel@tonic-gate */
168*0Sstevel@tonic-gate typedef LBER_SOCKET (NSLDAPI_SOCKET_FN)( LDAP *ld, int secure, int domain,
169*0Sstevel@tonic-gate int type, int protocol );
170*0Sstevel@tonic-gate typedef int (NSLDAPI_IOCTL_FN)( LBER_SOCKET s, int option, int *statusp );
171*0Sstevel@tonic-gate typedef int (NSLDAPI_CONNECT_WITH_TO_FN )( LBER_SOCKET s, struct sockaddr *name,
172*0Sstevel@tonic-gate int namelen, LDAP *ld);
173*0Sstevel@tonic-gate typedef int (NSLDAPI_CONNECT_FN )( LBER_SOCKET s, struct sockaddr *name,
174*0Sstevel@tonic-gate int namelen );
175*0Sstevel@tonic-gate typedef int (NSLDAPI_CLOSE_FN )( LBER_SOCKET s );
176*0Sstevel@tonic-gate
177*0Sstevel@tonic-gate static int nsldapi_try_each_host( LDAP *ld, const char *hostlist, int defport,
178*0Sstevel@tonic-gate int secure, NSLDAPI_SOCKET_FN *socketfn, NSLDAPI_IOCTL_FN *ioctlfn,
179*0Sstevel@tonic-gate NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
180*0Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn );
181*0Sstevel@tonic-gate
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate static int
nsldapi_os_closesocket(LBER_SOCKET s)184*0Sstevel@tonic-gate nsldapi_os_closesocket( LBER_SOCKET s )
185*0Sstevel@tonic-gate {
186*0Sstevel@tonic-gate int rc;
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gate #ifdef _WINDOWS
189*0Sstevel@tonic-gate rc = closesocket( s );
190*0Sstevel@tonic-gate #else
191*0Sstevel@tonic-gate rc = close( s );
192*0Sstevel@tonic-gate #endif
193*0Sstevel@tonic-gate return( rc );
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate static LBER_SOCKET
nsldapi_os_socket(LDAP * ld,int secure,int domain,int type,int protocol)198*0Sstevel@tonic-gate nsldapi_os_socket( LDAP *ld, int secure, int domain, int type, int protocol )
199*0Sstevel@tonic-gate {
200*0Sstevel@tonic-gate int s, invalid_socket;
201*0Sstevel@tonic-gate char *errmsg = NULL;
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate if ( secure ) {
204*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
205*0Sstevel@tonic-gate nsldapi_strdup( dgettext(TEXT_DOMAIN,
206*0Sstevel@tonic-gate "secure mode not supported") ));
207*0Sstevel@tonic-gate return( -1 );
208*0Sstevel@tonic-gate }
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate s = socket( domain, type, protocol );
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate /*
213*0Sstevel@tonic-gate * if the socket() call failed or it returned a socket larger
214*0Sstevel@tonic-gate * than we can deal with, return a "local error."
215*0Sstevel@tonic-gate */
216*0Sstevel@tonic-gate if ( NSLDAPI_INVALID_OS_SOCKET( s )) {
217*0Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN, "unable to create a socket");
218*0Sstevel@tonic-gate invalid_socket = 1;
219*0Sstevel@tonic-gate } else { /* valid socket -- check for overflow */
220*0Sstevel@tonic-gate invalid_socket = 0;
221*0Sstevel@tonic-gate #if !defined(NSLDAPI_HAVE_POLL) && !defined(_WINDOWS)
222*0Sstevel@tonic-gate /* not on Windows and do not have poll() */
223*0Sstevel@tonic-gate if ( s >= FD_SETSIZE ) {
224*0Sstevel@tonic-gate errmsg = "can't use socket >= FD_SETSIZE";
225*0Sstevel@tonic-gate }
226*0Sstevel@tonic-gate #endif
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate if ( errmsg != NULL ) { /* local socket error */
230*0Sstevel@tonic-gate if ( !invalid_socket ) {
231*0Sstevel@tonic-gate nsldapi_os_closesocket( s );
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate errmsg = nsldapi_strdup( errmsg );
234*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, errmsg );
235*0Sstevel@tonic-gate return( -1 );
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate return( s );
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gate /*
244*0Sstevel@tonic-gate * Non-blocking connect call function
245*0Sstevel@tonic-gate */
246*0Sstevel@tonic-gate static int
nsldapi_os_connect_with_to(LBER_SOCKET sockfd,struct sockaddr * saptr,int salen,LDAP * ld)247*0Sstevel@tonic-gate nsldapi_os_connect_with_to(LBER_SOCKET sockfd, struct sockaddr *saptr,
248*0Sstevel@tonic-gate int salen, LDAP *ld)
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate #ifndef _WINDOWS
251*0Sstevel@tonic-gate int flags;
252*0Sstevel@tonic-gate #endif /* _WINDOWS */
253*0Sstevel@tonic-gate int n, error;
254*0Sstevel@tonic-gate int len;
255*0Sstevel@tonic-gate fd_set rset, wset;
256*0Sstevel@tonic-gate struct timeval tval;
257*0Sstevel@tonic-gate #ifdef _WINDOWS
258*0Sstevel@tonic-gate int nonblock = 1;
259*0Sstevel@tonic-gate int block = 0;
260*0Sstevel@tonic-gate fd_set eset;
261*0Sstevel@tonic-gate #endif /* _WINDOWS */
262*0Sstevel@tonic-gate int msec = ld->ld_connect_timeout; /* milliseconds */
263*0Sstevel@tonic-gate int continue_on_intr = 0;
264*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
265*0Sstevel@tonic-gate hrtime_t start_time = 0, tmp_time, tv_time; /* nanoseconds */
266*0Sstevel@tonic-gate #else
267*0Sstevel@tonic-gate long start_time = 0, tmp_time; /* seconds */
268*0Sstevel@tonic-gate #endif
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_nonblock timeout: %d (msec)\n",
272*0Sstevel@tonic-gate msec, 0, 0);
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gate #ifdef _WINDOWS
275*0Sstevel@tonic-gate ioctlsocket(sockfd, FIONBIO, &nonblock);
276*0Sstevel@tonic-gate #else
277*0Sstevel@tonic-gate flags = fcntl(sockfd, F_GETFL, 0);
278*0Sstevel@tonic-gate fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
279*0Sstevel@tonic-gate #endif /* _WINDOWS */
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gate error = 0;
282*0Sstevel@tonic-gate if ((n = connect(sockfd, saptr, salen)) < 0)
283*0Sstevel@tonic-gate #ifdef _WINDOWS
284*0Sstevel@tonic-gate if ((n != SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) {
285*0Sstevel@tonic-gate #else
286*0Sstevel@tonic-gate if (errno != EINPROGRESS) {
287*0Sstevel@tonic-gate #endif /* _WINDOWS */
288*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
289*0Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_TRACE ) {
290*0Sstevel@tonic-gate perror("connect");
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate #endif
293*0Sstevel@tonic-gate return (-1);
294*0Sstevel@tonic-gate }
295*0Sstevel@tonic-gate
296*0Sstevel@tonic-gate /* success */
297*0Sstevel@tonic-gate if (n == 0)
298*0Sstevel@tonic-gate goto done;
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gate FD_ZERO(&rset);
301*0Sstevel@tonic-gate FD_SET(sockfd, &rset);
302*0Sstevel@tonic-gate wset = rset;
303*0Sstevel@tonic-gate
304*0Sstevel@tonic-gate #ifdef _WINDOWS
305*0Sstevel@tonic-gate eset = rset;
306*0Sstevel@tonic-gate #endif /* _WINDOWS */
307*0Sstevel@tonic-gate
308*0Sstevel@tonic-gate if (msec < 0 && msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) {
309*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "Invalid timeout value detected.."
310*0Sstevel@tonic-gate "resetting connect timeout to default value "
311*0Sstevel@tonic-gate "(LDAP_X_IO_TIMEOUT_NO_TIMEOUT\n", 0, 0, 0);
312*0Sstevel@tonic-gate msec = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
313*0Sstevel@tonic-gate } else {
314*0Sstevel@tonic-gate if (msec != 0) {
315*0Sstevel@tonic-gate tval.tv_sec = msec / MILLISEC;
316*0Sstevel@tonic-gate tval.tv_usec = (MICROSEC / MILLISEC) *
317*0Sstevel@tonic-gate (msec % MILLISEC);
318*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
319*0Sstevel@tonic-gate start_time = gethrtime();
320*0Sstevel@tonic-gate tv_time = (hrtime_t)msec * (NANOSEC / MILLISEC);
321*0Sstevel@tonic-gate #else
322*0Sstevel@tonic-gate start_time = (long)time(NULL);
323*0Sstevel@tonic-gate #endif
324*0Sstevel@tonic-gate } else {
325*0Sstevel@tonic-gate tval.tv_sec = 0;
326*0Sstevel@tonic-gate tval.tv_usec = 0;
327*0Sstevel@tonic-gate }
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gate /* if timeval structure == NULL, select will block indefinitely */
331*0Sstevel@tonic-gate /* != NULL, and value == 0, select will */
332*0Sstevel@tonic-gate /* not block */
333*0Sstevel@tonic-gate /* Windows is a bit quirky on how it behaves w.r.t nonblocking */
334*0Sstevel@tonic-gate /* connects. If the connect fails, the exception fd, eset, is */
335*0Sstevel@tonic-gate /* set to show the failure. The first argument in select is */
336*0Sstevel@tonic-gate /* ignored */
337*0Sstevel@tonic-gate
338*0Sstevel@tonic-gate #ifdef _WINDOWS
339*0Sstevel@tonic-gate if ((n = select(sockfd +1, &rset, &wset, &eset,
340*0Sstevel@tonic-gate (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) {
341*0Sstevel@tonic-gate errno = WSAETIMEDOUT;
342*0Sstevel@tonic-gate return (-1);
343*0Sstevel@tonic-gate }
344*0Sstevel@tonic-gate /* if wset is set, the connect worked */
345*0Sstevel@tonic-gate if (FD_ISSET(sockfd, &wset) || FD_ISSET(sockfd, &rset)) {
346*0Sstevel@tonic-gate len = sizeof(error);
347*0Sstevel@tonic-gate if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
348*0Sstevel@tonic-gate < 0)
349*0Sstevel@tonic-gate return (-1);
350*0Sstevel@tonic-gate goto done;
351*0Sstevel@tonic-gate }
352*0Sstevel@tonic-gate
353*0Sstevel@tonic-gate /* if eset is set, the connect failed */
354*0Sstevel@tonic-gate if (FD_ISSET(sockfd, &eset)) {
355*0Sstevel@tonic-gate return (-1);
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /* failure on select call */
359*0Sstevel@tonic-gate if (n == SOCKET_ERROR) {
360*0Sstevel@tonic-gate perror("select error: SOCKET_ERROR returned");
361*0Sstevel@tonic-gate return (-1);
362*0Sstevel@tonic-gate }
363*0Sstevel@tonic-gate #else
364*0Sstevel@tonic-gate /*
365*0Sstevel@tonic-gate * if LDAP_BITOPT_RESTART and select() is interrupted
366*0Sstevel@tonic-gate * try again.
367*0Sstevel@tonic-gate */
368*0Sstevel@tonic-gate do {
369*0Sstevel@tonic-gate continue_on_intr = 0;
370*0Sstevel@tonic-gate if ((n = select(sockfd +1, &rset, &wset, NULL,
371*0Sstevel@tonic-gate (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? \
372*0Sstevel@tonic-gate &tval : NULL)) == 0) {
373*0Sstevel@tonic-gate errno = ETIMEDOUT;
374*0Sstevel@tonic-gate return (-1);
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate if (n < 0) {
377*0Sstevel@tonic-gate if ((ld->ld_options & LDAP_BITOPT_RESTART) &&
378*0Sstevel@tonic-gate (errno == EINTR)) {
379*0Sstevel@tonic-gate continue_on_intr = 1;
380*0Sstevel@tonic-gate errno = 0;
381*0Sstevel@tonic-gate FD_ZERO(&rset);
382*0Sstevel@tonic-gate FD_SET(sockfd, &rset);
383*0Sstevel@tonic-gate wset = rset;
384*0Sstevel@tonic-gate /* honour the timeout */
385*0Sstevel@tonic-gate if ((msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) &&
386*0Sstevel@tonic-gate (msec != 0)) {
387*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
388*0Sstevel@tonic-gate tmp_time = gethrtime();
389*0Sstevel@tonic-gate if ((tv_time -=
390*0Sstevel@tonic-gate (tmp_time - start_time)) <= 0) {
391*0Sstevel@tonic-gate #else
392*0Sstevel@tonic-gate tmp_time = (long)time(NULL);
393*0Sstevel@tonic-gate if ((tval.tv_sec -=
394*0Sstevel@tonic-gate (tmp_time - start_time)) <= 0) {
395*0Sstevel@tonic-gate #endif
396*0Sstevel@tonic-gate /* timeout */
397*0Sstevel@tonic-gate errno = ETIMEDOUT;
398*0Sstevel@tonic-gate return (-1);
399*0Sstevel@tonic-gate }
400*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
401*0Sstevel@tonic-gate tval.tv_sec = tv_time / NANOSEC;
402*0Sstevel@tonic-gate tval.tv_usec = (tv_time % NANOSEC) /
403*0Sstevel@tonic-gate (NANOSEC / MICROSEC);
404*0Sstevel@tonic-gate #endif
405*0Sstevel@tonic-gate start_time = tmp_time;
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate } else {
408*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
409*0Sstevel@tonic-gate perror("select error: ");
410*0Sstevel@tonic-gate #endif
411*0Sstevel@tonic-gate return (-1);
412*0Sstevel@tonic-gate }
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate } while (continue_on_intr == 1);
415*0Sstevel@tonic-gate
416*0Sstevel@tonic-gate if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
417*0Sstevel@tonic-gate len = sizeof(error);
418*0Sstevel@tonic-gate if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
419*0Sstevel@tonic-gate < 0)
420*0Sstevel@tonic-gate return (-1);
421*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
422*0Sstevel@tonic-gate } else if ( ldap_debug & LDAP_DEBUG_TRACE ) {
423*0Sstevel@tonic-gate perror("select error: sockfd not set");
424*0Sstevel@tonic-gate #endif
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate #endif /* _WINDOWS */
427*0Sstevel@tonic-gate
428*0Sstevel@tonic-gate done:
429*0Sstevel@tonic-gate #ifdef _WINDOWS
430*0Sstevel@tonic-gate ioctlsocket(sockfd, FIONBIO, &block);
431*0Sstevel@tonic-gate #else
432*0Sstevel@tonic-gate fcntl(sockfd, F_SETFL, flags);
433*0Sstevel@tonic-gate #endif /* _WINDOWS */
434*0Sstevel@tonic-gate
435*0Sstevel@tonic-gate if (error) {
436*0Sstevel@tonic-gate errno = error;
437*0Sstevel@tonic-gate return (-1);
438*0Sstevel@tonic-gate }
439*0Sstevel@tonic-gate
440*0Sstevel@tonic-gate return (0);
441*0Sstevel@tonic-gate }
442*0Sstevel@tonic-gate
443*0Sstevel@tonic-gate
444*0Sstevel@tonic-gate static int
445*0Sstevel@tonic-gate nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp )
446*0Sstevel@tonic-gate {
447*0Sstevel@tonic-gate int err;
448*0Sstevel@tonic-gate #ifdef _WINDOWS
449*0Sstevel@tonic-gate u_long iostatus;
450*0Sstevel@tonic-gate #endif
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate if ( FIONBIO != option ) {
453*0Sstevel@tonic-gate return( -1 );
454*0Sstevel@tonic-gate }
455*0Sstevel@tonic-gate
456*0Sstevel@tonic-gate #ifdef _WINDOWS
457*0Sstevel@tonic-gate iostatus = *(u_long *)statusp;
458*0Sstevel@tonic-gate err = ioctlsocket( s, FIONBIO, &iostatus );
459*0Sstevel@tonic-gate #else
460*0Sstevel@tonic-gate err = ioctl( s, FIONBIO, (caddr_t)statusp );
461*0Sstevel@tonic-gate #endif
462*0Sstevel@tonic-gate
463*0Sstevel@tonic-gate return( err );
464*0Sstevel@tonic-gate }
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gate
467*0Sstevel@tonic-gate int
468*0Sstevel@tonic-gate nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *hostlist,
469*0Sstevel@tonic-gate int defport, int secure, char **krbinstancep )
470*0Sstevel@tonic-gate /*
471*0Sstevel@tonic-gate * "defport" must be in host byte order
472*0Sstevel@tonic-gate * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
473*0Sstevel@tonic-gate * if -1 is returned, ld_errno is set
474*0Sstevel@tonic-gate */
475*0Sstevel@tonic-gate {
476*0Sstevel@tonic-gate int s;
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_to_host: %s, port: %d\n",
479*0Sstevel@tonic-gate NULL == hostlist ? "NULL" : hostlist, defport, 0 );
480*0Sstevel@tonic-gate
481*0Sstevel@tonic-gate /*
482*0Sstevel@tonic-gate * If an extended I/O connect callback has been defined, just use it.
483*0Sstevel@tonic-gate */
484*0Sstevel@tonic-gate if ( NULL != ld->ld_extconnect_fn ) {
485*0Sstevel@tonic-gate unsigned long connect_opts = 0;
486*0Sstevel@tonic-gate
487*0Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
488*0Sstevel@tonic-gate connect_opts |= LDAP_X_EXTIOF_OPT_NONBLOCKING;
489*0Sstevel@tonic-gate }
490*0Sstevel@tonic-gate if ( secure ) {
491*0Sstevel@tonic-gate connect_opts |= LDAP_X_EXTIOF_OPT_SECURE;
492*0Sstevel@tonic-gate }
493*0Sstevel@tonic-gate s = ld->ld_extconnect_fn( hostlist, defport,
494*0Sstevel@tonic-gate ld->ld_connect_timeout, connect_opts,
495*0Sstevel@tonic-gate ld->ld_ext_session_arg,
496*0Sstevel@tonic-gate &sb->sb_ext_io_fns.lbextiofn_socket_arg
497*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
498*0Sstevel@tonic-gate , NULL );
499*0Sstevel@tonic-gate #else
500*0Sstevel@tonic-gate );
501*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
502*0Sstevel@tonic-gate
503*0Sstevel@tonic-gate } else {
504*0Sstevel@tonic-gate s = nsldapi_try_each_host( ld, hostlist,
505*0Sstevel@tonic-gate defport, secure, nsldapi_os_socket,
506*0Sstevel@tonic-gate nsldapi_os_ioctl, nsldapi_os_connect_with_to,
507*0Sstevel@tonic-gate NULL, nsldapi_os_closesocket );
508*0Sstevel@tonic-gate }
509*0Sstevel@tonic-gate
510*0Sstevel@tonic-gate if ( s < 0 ) {
511*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
512*0Sstevel@tonic-gate return( -1 );
513*0Sstevel@tonic-gate }
514*0Sstevel@tonic-gate
515*0Sstevel@tonic-gate sb->sb_sd = s;
516*0Sstevel@tonic-gate
517*0Sstevel@tonic-gate /*
518*0Sstevel@tonic-gate * Set krbinstancep (canonical name of host for use by Kerberos).
519*0Sstevel@tonic-gate */
520*0Sstevel@tonic-gate #ifdef KERBEROS
521*0Sstevel@tonic-gate char *p;
522*0Sstevel@tonic-gate
523*0Sstevel@tonic-gate if (( *krbinstancep = nsldapi_host_connected_to( sb )) != NULL
524*0Sstevel@tonic-gate && ( p = strchr( *krbinstancep, '.' )) != NULL ) {
525*0Sstevel@tonic-gate *p = '\0';
526*0Sstevel@tonic-gate }
527*0Sstevel@tonic-gate #else /* KERBEROS */
528*0Sstevel@tonic-gate *krbinstancep = NULL;
529*0Sstevel@tonic-gate #endif /* KERBEROS */
530*0Sstevel@tonic-gate
531*0Sstevel@tonic-gate return( 0 );
532*0Sstevel@tonic-gate }
533*0Sstevel@tonic-gate
534*0Sstevel@tonic-gate
535*0Sstevel@tonic-gate /*
536*0Sstevel@tonic-gate * Returns a socket number if successful and -1 if an error occurs.
537*0Sstevel@tonic-gate */
538*0Sstevel@tonic-gate static int
539*0Sstevel@tonic-gate nsldapi_try_each_host( LDAP *ld, const char *hostlist,
540*0Sstevel@tonic-gate int defport, int secure, NSLDAPI_SOCKET_FN *socketfn,
541*0Sstevel@tonic-gate NSLDAPI_IOCTL_FN *ioctlfn, NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
542*0Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn )
543*0Sstevel@tonic-gate {
544*0Sstevel@tonic-gate int rc, i, s, err, connected, use_hp;
545*0Sstevel@tonic-gate int parse_err, port;
546*0Sstevel@tonic-gate struct sockaddr_in sin;
547*0Sstevel@tonic-gate nsldapi_in_addr_t address;
548*0Sstevel@tonic-gate char **addrlist, *ldhpbuf, *ldhpbuf_allocd;
549*0Sstevel@tonic-gate char *host;
550*0Sstevel@tonic-gate LDAPHostEnt ldhent, *ldhp;
551*0Sstevel@tonic-gate struct hostent *hp;
552*0Sstevel@tonic-gate struct ldap_x_hostlist_status *status;
553*0Sstevel@tonic-gate #ifdef GETHOSTBYNAME_BUF_T
554*0Sstevel@tonic-gate GETHOSTBYNAME_BUF_T hbuf;
555*0Sstevel@tonic-gate struct hostent hent;
556*0Sstevel@tonic-gate #endif /* GETHOSTBYNAME_BUF_T */
557*0Sstevel@tonic-gate
558*0Sstevel@tonic-gate connected = 0;
559*0Sstevel@tonic-gate parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port,
560*0Sstevel@tonic-gate &status );
561*0Sstevel@tonic-gate while ( !connected && LDAP_SUCCESS == parse_err && host != NULL ) {
562*0Sstevel@tonic-gate ldhpbuf_allocd = NULL;
563*0Sstevel@tonic-gate ldhp = NULL;
564*0Sstevel@tonic-gate hp = NULL;
565*0Sstevel@tonic-gate s = 0;
566*0Sstevel@tonic-gate use_hp = 0;
567*0Sstevel@tonic-gate addrlist = NULL;
568*0Sstevel@tonic-gate
569*0Sstevel@tonic-gate
570*0Sstevel@tonic-gate if (( address = inet_addr( host )) == -1 ) {
571*0Sstevel@tonic-gate if ( ld->ld_dns_gethostbyname_fn == NULL ) {
572*0Sstevel@tonic-gate if (( hp = GETHOSTBYNAME( host, &hent, hbuf,
573*0Sstevel@tonic-gate sizeof(hbuf), &err )) != NULL ) {
574*0Sstevel@tonic-gate addrlist = hp->h_addr_list;
575*0Sstevel@tonic-gate }
576*0Sstevel@tonic-gate } else {
577*0Sstevel@tonic-gate /*
578*0Sstevel@tonic-gate * DNS callback installed... use it.
579*0Sstevel@tonic-gate */
580*0Sstevel@tonic-gate #ifdef GETHOSTBYNAME_buf_t
581*0Sstevel@tonic-gate /* avoid allocation by using hbuf if large enough */
582*0Sstevel@tonic-gate if ( sizeof( hbuf ) < ld->ld_dns_bufsize ) {
583*0Sstevel@tonic-gate ldhpbuf = ldhpbuf_allocd
584*0Sstevel@tonic-gate = NSLDAPI_MALLOC( ld->ld_dns_bufsize );
585*0Sstevel@tonic-gate } else {
586*0Sstevel@tonic-gate ldhpbuf = (char *)hbuf;
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate #else /* GETHOSTBYNAME_buf_t */
589*0Sstevel@tonic-gate ldhpbuf = ldhpbuf_allocd = NSLDAPI_MALLOC(
590*0Sstevel@tonic-gate ld->ld_dns_bufsize );
591*0Sstevel@tonic-gate #endif /* else GETHOSTBYNAME_buf_t */
592*0Sstevel@tonic-gate
593*0Sstevel@tonic-gate if ( ldhpbuf == NULL ) {
594*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY,
595*0Sstevel@tonic-gate NULL, NULL );
596*0Sstevel@tonic-gate ldap_memfree( host );
597*0Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
598*0Sstevel@tonic-gate return( -1 );
599*0Sstevel@tonic-gate }
600*0Sstevel@tonic-gate
601*0Sstevel@tonic-gate if (( ldhp = ld->ld_dns_gethostbyname_fn( host,
602*0Sstevel@tonic-gate &ldhent, ldhpbuf, ld->ld_dns_bufsize, &err,
603*0Sstevel@tonic-gate ld->ld_dns_extradata )) != NULL ) {
604*0Sstevel@tonic-gate addrlist = ldhp->ldaphe_addr_list;
605*0Sstevel@tonic-gate }
606*0Sstevel@tonic-gate }
607*0Sstevel@tonic-gate
608*0Sstevel@tonic-gate if ( addrlist == NULL ) {
609*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
610*0Sstevel@tonic-gate LDAP_SET_ERRNO( ld, EHOSTUNREACH ); /* close enough */
611*0Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
612*0Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
613*0Sstevel@tonic-gate }
614*0Sstevel@tonic-gate ldap_memfree( host );
615*0Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
616*0Sstevel@tonic-gate return( -1 );
617*0Sstevel@tonic-gate }
618*0Sstevel@tonic-gate use_hp = 1;
619*0Sstevel@tonic-gate }
620*0Sstevel@tonic-gate
621*0Sstevel@tonic-gate rc = -1;
622*0Sstevel@tonic-gate for ( i = 0; !use_hp || ( addrlist[ i ] != 0 ); i++ ) {
623*0Sstevel@tonic-gate if ( -1 == ( s = (*socketfn)( ld, secure, AF_INET,
624*0Sstevel@tonic-gate SOCK_STREAM, 0 ))) {
625*0Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
626*0Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate ldap_memfree( host );
629*0Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
630*0Sstevel@tonic-gate return( -1 );
631*0Sstevel@tonic-gate }
632*0Sstevel@tonic-gate
633*0Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC ) {
634*0Sstevel@tonic-gate int iostatus = 1;
635*0Sstevel@tonic-gate
636*0Sstevel@tonic-gate err = (*ioctlfn)( s, FIONBIO, &iostatus );
637*0Sstevel@tonic-gate if ( err == -1 ) {
638*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
639*0Sstevel@tonic-gate "FIONBIO ioctl failed on %d\n",
640*0Sstevel@tonic-gate s, 0, 0 );
641*0Sstevel@tonic-gate }
642*0Sstevel@tonic-gate }
643*0Sstevel@tonic-gate
644*0Sstevel@tonic-gate (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
645*0Sstevel@tonic-gate sin.sin_family = AF_INET;
646*0Sstevel@tonic-gate sin.sin_port = htons( (unsigned short)port );
647*0Sstevel@tonic-gate
648*0Sstevel@tonic-gate SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
649*0Sstevel@tonic-gate ( use_hp ? (char *) addrlist[ i ] :
650*0Sstevel@tonic-gate (char *) &address ), sizeof( sin.sin_addr.s_addr) );
651*0Sstevel@tonic-gate
652*0Sstevel@tonic-gate {
653*0Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
654*0Sstevel@tonic-gate /*
655*0Sstevel@tonic-gate * Block all of the signals that might interrupt connect() since there
656*0Sstevel@tonic-gate * is an OS bug that causes connect() to fail if it is restarted. Look in
657*0Sstevel@tonic-gate * ns/netsite/ldap/include/portable.h for the definition of
658*0Sstevel@tonic-gate * LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
659*0Sstevel@tonic-gate */
660*0Sstevel@tonic-gate sigset_t ints_off, oldset;
661*0Sstevel@tonic-gate
662*0Sstevel@tonic-gate sigemptyset( &ints_off );
663*0Sstevel@tonic-gate sigaddset( &ints_off, SIGALRM );
664*0Sstevel@tonic-gate sigaddset( &ints_off, SIGIO );
665*0Sstevel@tonic-gate sigaddset( &ints_off, SIGCLD );
666*0Sstevel@tonic-gate
667*0Sstevel@tonic-gate sigprocmask( SIG_BLOCK, &ints_off, &oldset );
668*0Sstevel@tonic-gate #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
669*0Sstevel@tonic-gate
670*0Sstevel@tonic-gate if ( NULL != connectwithtofn ) {
671*0Sstevel@tonic-gate err = (*connectwithtofn)(s,
672*0Sstevel@tonic-gate (struct sockaddr *)&sin,
673*0Sstevel@tonic-gate sizeof(struct sockaddr_in),
674*0Sstevel@tonic-gate ld);
675*0Sstevel@tonic-gate } else {
676*0Sstevel@tonic-gate err = (*connectfn)(s,
677*0Sstevel@tonic-gate (struct sockaddr *)&sin,
678*0Sstevel@tonic-gate sizeof(struct sockaddr_in));
679*0Sstevel@tonic-gate }
680*0Sstevel@tonic-gate #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
681*0Sstevel@tonic-gate /*
682*0Sstevel@tonic-gate * restore original signal mask
683*0Sstevel@tonic-gate */
684*0Sstevel@tonic-gate sigprocmask( SIG_SETMASK, &oldset, 0 );
685*0Sstevel@tonic-gate #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
686*0Sstevel@tonic-gate
687*0Sstevel@tonic-gate }
688*0Sstevel@tonic-gate if ( err >= 0 ) {
689*0Sstevel@tonic-gate connected = 1;
690*0Sstevel@tonic-gate rc = 0;
691*0Sstevel@tonic-gate break;
692*0Sstevel@tonic-gate } else {
693*0Sstevel@tonic-gate if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
694*0Sstevel@tonic-gate #ifdef _WINDOWS
695*0Sstevel@tonic-gate if (err == -1 && WSAGetLastError() == WSAEWOULDBLOCK)
696*0Sstevel@tonic-gate LDAP_SET_ERRNO( ld, EWOULDBLOCK );
697*0Sstevel@tonic-gate #endif /* _WINDOWS */
698*0Sstevel@tonic-gate err = LDAP_GET_ERRNO( ld );
699*0Sstevel@tonic-gate if ( NSLDAPI_ERRNO_IO_INPROGRESS( err )) {
700*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "connect would block...\n",
701*0Sstevel@tonic-gate 0, 0, 0 );
702*0Sstevel@tonic-gate rc = -2;
703*0Sstevel@tonic-gate break;
704*0Sstevel@tonic-gate }
705*0Sstevel@tonic-gate }
706*0Sstevel@tonic-gate
707*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
708*0Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_TRACE ) {
709*0Sstevel@tonic-gate perror( (char *)inet_ntoa( sin.sin_addr ));
710*0Sstevel@tonic-gate }
711*0Sstevel@tonic-gate #endif
712*0Sstevel@tonic-gate (*closefn)( s );
713*0Sstevel@tonic-gate if ( !use_hp ) {
714*0Sstevel@tonic-gate break;
715*0Sstevel@tonic-gate }
716*0Sstevel@tonic-gate }
717*0Sstevel@tonic-gate }
718*0Sstevel@tonic-gate
719*0Sstevel@tonic-gate ldap_memfree( host );
720*0Sstevel@tonic-gate parse_err = ldap_x_hostlist_next( &host, &port, status );
721*0Sstevel@tonic-gate }
722*0Sstevel@tonic-gate
723*0Sstevel@tonic-gate if ( ldhpbuf_allocd != NULL ) {
724*0Sstevel@tonic-gate NSLDAPI_FREE( ldhpbuf_allocd );
725*0Sstevel@tonic-gate }
726*0Sstevel@tonic-gate ldap_memfree( host );
727*0Sstevel@tonic-gate ldap_x_hostlist_statusfree( status );
728*0Sstevel@tonic-gate
729*0Sstevel@tonic-gate if ( connected ) {
730*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
731*0Sstevel@tonic-gate s, inet_ntoa( sin.sin_addr ), 0 );
732*0Sstevel@tonic-gate }
733*0Sstevel@tonic-gate
734*0Sstevel@tonic-gate return( rc == 0 ? s : -1 );
735*0Sstevel@tonic-gate }
736*0Sstevel@tonic-gate
737*0Sstevel@tonic-gate
738*0Sstevel@tonic-gate void
739*0Sstevel@tonic-gate nsldapi_close_connection( LDAP *ld, Sockbuf *sb )
740*0Sstevel@tonic-gate {
741*0Sstevel@tonic-gate if ( ld->ld_extclose_fn == NULL ) {
742*0Sstevel@tonic-gate nsldapi_os_closesocket( sb->sb_sd );
743*0Sstevel@tonic-gate } else {
744*0Sstevel@tonic-gate ld->ld_extclose_fn( sb->sb_sd,
745*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg );
746*0Sstevel@tonic-gate }
747*0Sstevel@tonic-gate }
748*0Sstevel@tonic-gate
749*0Sstevel@tonic-gate
750*0Sstevel@tonic-gate #ifdef KERBEROS
751*0Sstevel@tonic-gate char *
752*0Sstevel@tonic-gate nsldapi_host_connected_to( Sockbuf *sb )
753*0Sstevel@tonic-gate {
754*0Sstevel@tonic-gate struct hostent *hp;
755*0Sstevel@tonic-gate char *p;
756*0Sstevel@tonic-gate int len;
757*0Sstevel@tonic-gate struct sockaddr_in sin;
758*0Sstevel@tonic-gate
759*0Sstevel@tonic-gate (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
760*0Sstevel@tonic-gate len = sizeof( sin );
761*0Sstevel@tonic-gate if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
762*0Sstevel@tonic-gate return( NULL );
763*0Sstevel@tonic-gate }
764*0Sstevel@tonic-gate
765*0Sstevel@tonic-gate /*
766*0Sstevel@tonic-gate * do a reverse lookup on the addr to get the official hostname.
767*0Sstevel@tonic-gate * this is necessary for kerberos to work right, since the official
768*0Sstevel@tonic-gate * hostname is used as the kerberos instance.
769*0Sstevel@tonic-gate */
770*0Sstevel@tonic-gate #error XXXmcs: need to use DNS callbacks here
771*0Sstevel@tonic-gate if (( hp = gethostbyaddr((char *) &sin.sin_addr,
772*0Sstevel@tonic-gate sizeof( sin.sin_addr ), AF_INET)) != NULL ) {
773*0Sstevel@tonic-gate if ( hp->h_name != NULL ) {
774*0Sstevel@tonic-gate return( nsldapi_strdup( hp->h_name ));
775*0Sstevel@tonic-gate }
776*0Sstevel@tonic-gate }
777*0Sstevel@tonic-gate
778*0Sstevel@tonic-gate return( NULL );
779*0Sstevel@tonic-gate }
780*0Sstevel@tonic-gate #endif /* KERBEROS */
781*0Sstevel@tonic-gate
782*0Sstevel@tonic-gate
783*0Sstevel@tonic-gate /*
784*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
785*0Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
786*0Sstevel@tonic-gate */
787*0Sstevel@tonic-gate int
788*0Sstevel@tonic-gate nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb )
789*0Sstevel@tonic-gate {
790*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
791*0Sstevel@tonic-gate
792*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
793*0Sstevel@tonic-gate
794*0Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
795*0Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
796*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
797*0Sstevel@tonic-gate return( -1 );
798*0Sstevel@tonic-gate }
799*0Sstevel@tonic-gate
800*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
801*0Sstevel@tonic-gate
802*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
803*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
804*0Sstevel@tonic-gate if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
805*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLOUT )) {
806*0Sstevel@tonic-gate ++iosp->ios_write_count;
807*0Sstevel@tonic-gate }
808*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
809*0Sstevel@tonic-gate if ( !FD_ISSET( sb->sb_sd,
810*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds )) {
811*0Sstevel@tonic-gate FD_SET( sb->sb_sd,
812*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds );
813*0Sstevel@tonic-gate ++iosp->ios_write_count;
814*0Sstevel@tonic-gate }
815*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
816*0Sstevel@tonic-gate
817*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
818*0Sstevel@tonic-gate if ( nsldapi_add_to_cb_pollfds( sb,
819*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
820*0Sstevel@tonic-gate ++iosp->ios_write_count;
821*0Sstevel@tonic-gate }
822*0Sstevel@tonic-gate
823*0Sstevel@tonic-gate } else {
824*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
825*0Sstevel@tonic-gate "nsldapi_iostatus_interest_write: unknown I/O type %d\n",
826*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
827*0Sstevel@tonic-gate }
828*0Sstevel@tonic-gate
829*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
830*0Sstevel@tonic-gate
831*0Sstevel@tonic-gate return( 0 );
832*0Sstevel@tonic-gate }
833*0Sstevel@tonic-gate
834*0Sstevel@tonic-gate
835*0Sstevel@tonic-gate /*
836*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
837*0Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
838*0Sstevel@tonic-gate */
839*0Sstevel@tonic-gate int
840*0Sstevel@tonic-gate nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb )
841*0Sstevel@tonic-gate {
842*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
843*0Sstevel@tonic-gate
844*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
845*0Sstevel@tonic-gate
846*0Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
847*0Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
848*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
849*0Sstevel@tonic-gate return( -1 );
850*0Sstevel@tonic-gate }
851*0Sstevel@tonic-gate
852*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
853*0Sstevel@tonic-gate
854*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
855*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
856*0Sstevel@tonic-gate if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
857*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLIN )) {
858*0Sstevel@tonic-gate ++iosp->ios_read_count;
859*0Sstevel@tonic-gate }
860*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
861*0Sstevel@tonic-gate if ( !FD_ISSET( sb->sb_sd,
862*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds )) {
863*0Sstevel@tonic-gate FD_SET( sb->sb_sd,
864*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds );
865*0Sstevel@tonic-gate ++iosp->ios_read_count;
866*0Sstevel@tonic-gate }
867*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
868*0Sstevel@tonic-gate
869*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
870*0Sstevel@tonic-gate if ( nsldapi_add_to_cb_pollfds( sb,
871*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
872*0Sstevel@tonic-gate ++iosp->ios_read_count;
873*0Sstevel@tonic-gate }
874*0Sstevel@tonic-gate } else {
875*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
876*0Sstevel@tonic-gate "nsldapi_iostatus_interest_read: unknown I/O type %d\n",
877*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
878*0Sstevel@tonic-gate }
879*0Sstevel@tonic-gate
880*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
881*0Sstevel@tonic-gate
882*0Sstevel@tonic-gate return( 0 );
883*0Sstevel@tonic-gate }
884*0Sstevel@tonic-gate
885*0Sstevel@tonic-gate
886*0Sstevel@tonic-gate /*
887*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
888*0Sstevel@tonic-gate * Also allocates initializes ld->ld_iostatus if needed..
889*0Sstevel@tonic-gate */
890*0Sstevel@tonic-gate int
891*0Sstevel@tonic-gate nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb )
892*0Sstevel@tonic-gate {
893*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
894*0Sstevel@tonic-gate
895*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
896*0Sstevel@tonic-gate
897*0Sstevel@tonic-gate if ( ld->ld_iostatus == NULL
898*0Sstevel@tonic-gate && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
899*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
900*0Sstevel@tonic-gate return( -1 );
901*0Sstevel@tonic-gate }
902*0Sstevel@tonic-gate
903*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
904*0Sstevel@tonic-gate
905*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
906*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
907*0Sstevel@tonic-gate if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
908*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLOUT )) {
909*0Sstevel@tonic-gate --iosp->ios_write_count;
910*0Sstevel@tonic-gate }
911*0Sstevel@tonic-gate if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
912*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, POLLIN )) {
913*0Sstevel@tonic-gate --iosp->ios_read_count;
914*0Sstevel@tonic-gate }
915*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
916*0Sstevel@tonic-gate if ( FD_ISSET( sb->sb_sd,
917*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds )) {
918*0Sstevel@tonic-gate FD_CLR( sb->sb_sd,
919*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_writefds );
920*0Sstevel@tonic-gate --iosp->ios_write_count;
921*0Sstevel@tonic-gate }
922*0Sstevel@tonic-gate if ( FD_ISSET( sb->sb_sd,
923*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds )) {
924*0Sstevel@tonic-gate FD_CLR( sb->sb_sd,
925*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_readfds );
926*0Sstevel@tonic-gate --iosp->ios_read_count;
927*0Sstevel@tonic-gate }
928*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
929*0Sstevel@tonic-gate
930*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
931*0Sstevel@tonic-gate if ( nsldapi_clear_from_cb_pollfds( sb,
932*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
933*0Sstevel@tonic-gate --iosp->ios_write_count;
934*0Sstevel@tonic-gate }
935*0Sstevel@tonic-gate if ( nsldapi_clear_from_cb_pollfds( sb,
936*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
937*0Sstevel@tonic-gate --iosp->ios_read_count;
938*0Sstevel@tonic-gate }
939*0Sstevel@tonic-gate } else {
940*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
941*0Sstevel@tonic-gate "nsldapi_iostatus_interest_clear: unknown I/O type %d\n",
942*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
943*0Sstevel@tonic-gate }
944*0Sstevel@tonic-gate
945*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
946*0Sstevel@tonic-gate
947*0Sstevel@tonic-gate return( 0 );
948*0Sstevel@tonic-gate }
949*0Sstevel@tonic-gate
950*0Sstevel@tonic-gate
951*0Sstevel@tonic-gate /*
952*0Sstevel@tonic-gate * Return a non-zero value if sb is ready for write.
953*0Sstevel@tonic-gate */
954*0Sstevel@tonic-gate int
955*0Sstevel@tonic-gate nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb )
956*0Sstevel@tonic-gate {
957*0Sstevel@tonic-gate int rc;
958*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
959*0Sstevel@tonic-gate
960*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
961*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
962*0Sstevel@tonic-gate
963*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
964*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
965*0Sstevel@tonic-gate /*
966*0Sstevel@tonic-gate * if we are using poll() we do something a little tricky: if
967*0Sstevel@tonic-gate * any bits in the socket's returned events field other than
968*0Sstevel@tonic-gate * POLLIN (ready for read) are set, we return true. This
969*0Sstevel@tonic-gate * is done so we notice when a server closes a connection
970*0Sstevel@tonic-gate * or when another error occurs. The actual error will be
971*0Sstevel@tonic-gate * noticed later when we call write() or send().
972*0Sstevel@tonic-gate */
973*0Sstevel@tonic-gate rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
974*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, ~POLLIN );
975*0Sstevel@tonic-gate
976*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
977*0Sstevel@tonic-gate rc = FD_ISSET( sb->sb_sd,
978*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_writefds );
979*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
980*0Sstevel@tonic-gate
981*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
982*0Sstevel@tonic-gate rc = nsldapi_find_in_cb_pollfds( sb,
983*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLIN );
984*0Sstevel@tonic-gate
985*0Sstevel@tonic-gate } else {
986*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
987*0Sstevel@tonic-gate "nsldapi_iostatus_is_write_ready: unknown I/O type %d\n",
988*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
989*0Sstevel@tonic-gate rc = 0;
990*0Sstevel@tonic-gate }
991*0Sstevel@tonic-gate
992*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
993*0Sstevel@tonic-gate return( rc );
994*0Sstevel@tonic-gate }
995*0Sstevel@tonic-gate
996*0Sstevel@tonic-gate
997*0Sstevel@tonic-gate /*
998*0Sstevel@tonic-gate * Return a non-zero value if sb is ready for read.
999*0Sstevel@tonic-gate */
1000*0Sstevel@tonic-gate int
1001*0Sstevel@tonic-gate nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb )
1002*0Sstevel@tonic-gate {
1003*0Sstevel@tonic-gate int rc;
1004*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
1005*0Sstevel@tonic-gate
1006*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
1007*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
1008*0Sstevel@tonic-gate
1009*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1010*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1011*0Sstevel@tonic-gate /*
1012*0Sstevel@tonic-gate * if we are using poll() we do something a little tricky: if
1013*0Sstevel@tonic-gate * any bits in the socket's returned events field other than
1014*0Sstevel@tonic-gate * POLLOUT (ready for write) are set, we return true. This
1015*0Sstevel@tonic-gate * is done so we notice when a server closes a connection
1016*0Sstevel@tonic-gate * or when another error occurs. The actual error will be
1017*0Sstevel@tonic-gate * noticed later when we call read() or recv().
1018*0Sstevel@tonic-gate */
1019*0Sstevel@tonic-gate rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
1020*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo, ~POLLOUT );
1021*0Sstevel@tonic-gate
1022*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
1023*0Sstevel@tonic-gate rc = FD_ISSET( sb->sb_sd,
1024*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_readfds );
1025*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
1026*0Sstevel@tonic-gate
1027*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1028*0Sstevel@tonic-gate rc = nsldapi_find_in_cb_pollfds( sb,
1029*0Sstevel@tonic-gate &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLOUT );
1030*0Sstevel@tonic-gate
1031*0Sstevel@tonic-gate } else {
1032*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
1033*0Sstevel@tonic-gate "nsldapi_iostatus_is_read_ready: unknown I/O type %d\n",
1034*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
1035*0Sstevel@tonic-gate rc = 0;
1036*0Sstevel@tonic-gate }
1037*0Sstevel@tonic-gate
1038*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
1039*0Sstevel@tonic-gate return( rc );
1040*0Sstevel@tonic-gate }
1041*0Sstevel@tonic-gate
1042*0Sstevel@tonic-gate
1043*0Sstevel@tonic-gate /*
1044*0Sstevel@tonic-gate * Allocated and initialize ld->ld_iostatus if not already done.
1045*0Sstevel@tonic-gate * Should be called with LDAP_IOSTATUS_LOCK locked.
1046*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not (sets error in ld)
1047*0Sstevel@tonic-gate */
1048*0Sstevel@tonic-gate static int
1049*0Sstevel@tonic-gate nsldapi_iostatus_init_nolock( LDAP *ld )
1050*0Sstevel@tonic-gate {
1051*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
1052*0Sstevel@tonic-gate
1053*0Sstevel@tonic-gate if ( ld->ld_iostatus != NULL ) {
1054*0Sstevel@tonic-gate return( 0 );
1055*0Sstevel@tonic-gate }
1056*0Sstevel@tonic-gate
1057*0Sstevel@tonic-gate if (( iosp = (NSLDAPIIOStatus *)NSLDAPI_CALLOC( 1,
1058*0Sstevel@tonic-gate sizeof( NSLDAPIIOStatus ))) == NULL ) {
1059*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
1060*0Sstevel@tonic-gate return( -1 );
1061*0Sstevel@tonic-gate }
1062*0Sstevel@tonic-gate
1063*0Sstevel@tonic-gate if ( ld->ld_extpoll_fn == NULL ) {
1064*0Sstevel@tonic-gate iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_OSNATIVE;
1065*0Sstevel@tonic-gate #ifndef NSLDAPI_HAVE_POLL
1066*0Sstevel@tonic-gate FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_readfds );
1067*0Sstevel@tonic-gate FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_writefds );
1068*0Sstevel@tonic-gate #endif /* !NSLDAPI_HAVE_POLL */
1069*0Sstevel@tonic-gate
1070*0Sstevel@tonic-gate } else {
1071*0Sstevel@tonic-gate iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_CALLBACK;
1072*0Sstevel@tonic-gate }
1073*0Sstevel@tonic-gate
1074*0Sstevel@tonic-gate ld->ld_iostatus = iosp;
1075*0Sstevel@tonic-gate return( 0 );
1076*0Sstevel@tonic-gate }
1077*0Sstevel@tonic-gate
1078*0Sstevel@tonic-gate
1079*0Sstevel@tonic-gate void
1080*0Sstevel@tonic-gate nsldapi_iostatus_free( LDAP *ld )
1081*0Sstevel@tonic-gate {
1082*0Sstevel@tonic-gate if ( ld == NULL ) {
1083*0Sstevel@tonic-gate return;
1084*0Sstevel@tonic-gate }
1085*0Sstevel@tonic-gate
1086*0Sstevel@tonic-gate
1087*0Sstevel@tonic-gate /* clean up classic I/O compatibility glue */
1088*0Sstevel@tonic-gate if ( ld->ld_io_fns_ptr != NULL ) {
1089*0Sstevel@tonic-gate if ( ld->ld_ext_session_arg != NULL ) {
1090*0Sstevel@tonic-gate NSLDAPI_FREE( ld->ld_ext_session_arg );
1091*0Sstevel@tonic-gate }
1092*0Sstevel@tonic-gate NSLDAPI_FREE( ld->ld_io_fns_ptr );
1093*0Sstevel@tonic-gate }
1094*0Sstevel@tonic-gate
1095*0Sstevel@tonic-gate /* clean up I/O status tracking info. */
1096*0Sstevel@tonic-gate if ( ld->ld_iostatus != NULL ) {
1097*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp = ld->ld_iostatus;
1098*0Sstevel@tonic-gate
1099*0Sstevel@tonic-gate if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1100*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1101*0Sstevel@tonic-gate if ( iosp->ios_status.ios_osinfo.ossi_pollfds
1102*0Sstevel@tonic-gate != NULL ) {
1103*0Sstevel@tonic-gate NSLDAPI_FREE(
1104*0Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_pollfds );
1105*0Sstevel@tonic-gate }
1106*0Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
1107*0Sstevel@tonic-gate
1108*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1109*0Sstevel@tonic-gate if ( iosp->ios_status.ios_cbinfo.cbsi_pollfds
1110*0Sstevel@tonic-gate != NULL ) {
1111*0Sstevel@tonic-gate NSLDAPI_FREE(
1112*0Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds );
1113*0Sstevel@tonic-gate }
1114*0Sstevel@tonic-gate } else {
1115*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
1116*0Sstevel@tonic-gate "nsldapi_iostatus_free: unknown I/O type %d\n",
1117*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
1118*0Sstevel@tonic-gate }
1119*0Sstevel@tonic-gate
1120*0Sstevel@tonic-gate NSLDAPI_FREE( iosp );
1121*0Sstevel@tonic-gate }
1122*0Sstevel@tonic-gate }
1123*0Sstevel@tonic-gate
1124*0Sstevel@tonic-gate
1125*0Sstevel@tonic-gate static int
1126*0Sstevel@tonic-gate nsldapi_get_select_table_size( void )
1127*0Sstevel@tonic-gate {
1128*0Sstevel@tonic-gate static int tblsize = 0; /* static */
1129*0Sstevel@tonic-gate
1130*0Sstevel@tonic-gate if ( tblsize == 0 ) {
1131*0Sstevel@tonic-gate #if defined(_WINDOWS) || defined(XP_OS2)
1132*0Sstevel@tonic-gate tblsize = FOPEN_MAX; /* ANSI spec. */
1133*0Sstevel@tonic-gate #else
1134*0Sstevel@tonic-gate #ifdef USE_SYSCONF
1135*0Sstevel@tonic-gate tblsize = sysconf( _SC_OPEN_MAX );
1136*0Sstevel@tonic-gate #else /* USE_SYSCONF */
1137*0Sstevel@tonic-gate tblsize = getdtablesize();
1138*0Sstevel@tonic-gate #endif /* else USE_SYSCONF */
1139*0Sstevel@tonic-gate #endif /* else _WINDOWS */
1140*0Sstevel@tonic-gate
1141*0Sstevel@tonic-gate if ( tblsize >= FD_SETSIZE ) {
1142*0Sstevel@tonic-gate /*
1143*0Sstevel@tonic-gate * clamp value so we don't overrun the fd_set structure
1144*0Sstevel@tonic-gate */
1145*0Sstevel@tonic-gate tblsize = FD_SETSIZE - 1;
1146*0Sstevel@tonic-gate }
1147*0Sstevel@tonic-gate }
1148*0Sstevel@tonic-gate
1149*0Sstevel@tonic-gate return( tblsize );
1150*0Sstevel@tonic-gate }
1151*0Sstevel@tonic-gate
1152*0Sstevel@tonic-gate static int
1153*0Sstevel@tonic-gate nsldapi_tv2ms( struct timeval *tv )
1154*0Sstevel@tonic-gate {
1155*0Sstevel@tonic-gate if ( tv == NULL ) {
1156*0Sstevel@tonic-gate return( -1 ); /* infinite timout for poll() */
1157*0Sstevel@tonic-gate }
1158*0Sstevel@tonic-gate
1159*0Sstevel@tonic-gate return( tv->tv_sec * 1000 + tv->tv_usec / 1000 );
1160*0Sstevel@tonic-gate }
1161*0Sstevel@tonic-gate
1162*0Sstevel@tonic-gate
1163*0Sstevel@tonic-gate int
1164*0Sstevel@tonic-gate nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout )
1165*0Sstevel@tonic-gate {
1166*0Sstevel@tonic-gate int rc;
1167*0Sstevel@tonic-gate NSLDAPIIOStatus *iosp;
1168*0Sstevel@tonic-gate
1169*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_iostatus_poll\n", 0, 0, 0 );
1170*0Sstevel@tonic-gate
1171*0Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
1172*0Sstevel@tonic-gate iosp = ld->ld_iostatus;
1173*0Sstevel@tonic-gate
1174*0Sstevel@tonic-gate if ( iosp == NULL ||
1175*0Sstevel@tonic-gate ( iosp->ios_read_count <= 0 && iosp->ios_read_count <= 0 )) {
1176*0Sstevel@tonic-gate rc = 0; /* simulate a timeout */
1177*0Sstevel@tonic-gate
1178*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1179*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1180*0Sstevel@tonic-gate
1181*0Sstevel@tonic-gate rc = NSLDAPI_POLL( iosp->ios_status.ios_osinfo.ossi_pollfds,
1182*0Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_pollfds_size,
1183*0Sstevel@tonic-gate nsldapi_tv2ms( timeout ));
1184*0Sstevel@tonic-gate
1185*0Sstevel@tonic-gate #else /* NSLDAPI_HAVE_POLL */
1186*0Sstevel@tonic-gate
1187*0Sstevel@tonic-gate /* two (potentially large) struct copies */
1188*0Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_use_readfds
1189*0Sstevel@tonic-gate = iosp->ios_status.ios_osinfo.ossi_readfds;
1190*0Sstevel@tonic-gate iosp->ios_status.ios_osinfo.ossi_use_writefds
1191*0Sstevel@tonic-gate = iosp->ios_status.ios_osinfo.ossi_writefds;
1192*0Sstevel@tonic-gate
1193*0Sstevel@tonic-gate #ifdef HPUX9
1194*0Sstevel@tonic-gate rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
1195*0Sstevel@tonic-gate (int *)&iosp->ios_status.ios_osinfo.ossi_use_readfds
1196*0Sstevel@tonic-gate (int *)&iosp->ios_status.ios_osinfo.ossi_use_writefds,
1197*0Sstevel@tonic-gate NULL, timeout );
1198*0Sstevel@tonic-gate #else
1199*0Sstevel@tonic-gate rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
1200*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_readfds,
1201*0Sstevel@tonic-gate &iosp->ios_status.ios_osinfo.ossi_use_writefds,
1202*0Sstevel@tonic-gate NULL, timeout );
1203*0Sstevel@tonic-gate #endif /* else HPUX9 */
1204*0Sstevel@tonic-gate #endif /* else NSLDAPI_HAVE_POLL */
1205*0Sstevel@tonic-gate
1206*0Sstevel@tonic-gate } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1207*0Sstevel@tonic-gate /*
1208*0Sstevel@tonic-gate * We always pass the session extended I/O argument to
1209*0Sstevel@tonic-gate * the extended poll() callback.
1210*0Sstevel@tonic-gate */
1211*0Sstevel@tonic-gate rc = ld->ld_extpoll_fn(
1212*0Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds,
1213*0Sstevel@tonic-gate iosp->ios_status.ios_cbinfo.cbsi_pollfds_size,
1214*0Sstevel@tonic-gate nsldapi_tv2ms( timeout ), ld->ld_ext_session_arg );
1215*0Sstevel@tonic-gate
1216*0Sstevel@tonic-gate } else {
1217*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
1218*0Sstevel@tonic-gate "nsldapi_iostatus_poll: unknown I/O type %d\n",
1219*0Sstevel@tonic-gate iosp->ios_type, 0, 0 );
1220*0Sstevel@tonic-gate rc = 0; /* simulate a timeout (what else to do?) */
1221*0Sstevel@tonic-gate }
1222*0Sstevel@tonic-gate
1223*0Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
1224*0Sstevel@tonic-gate return( rc );
1225*0Sstevel@tonic-gate }
1226*0Sstevel@tonic-gate
1227*0Sstevel@tonic-gate
1228*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1229*0Sstevel@tonic-gate /*
1230*0Sstevel@tonic-gate * returns 1 if "fd" was added to pollfds.
1231*0Sstevel@tonic-gate * returns 1 if some of the bits in "events" were added to pollfds.
1232*0Sstevel@tonic-gate * returns 0 if no changes were made.
1233*0Sstevel@tonic-gate */
1234*0Sstevel@tonic-gate static int
1235*0Sstevel@tonic-gate nsldapi_add_to_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1236*0Sstevel@tonic-gate short events )
1237*0Sstevel@tonic-gate {
1238*0Sstevel@tonic-gate int i, openslot;
1239*0Sstevel@tonic-gate
1240*0Sstevel@tonic-gate /* first we check to see if "fd" is already in our pollfds */
1241*0Sstevel@tonic-gate openslot = -1;
1242*0Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1243*0Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].fd == fd ) {
1244*0Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].events & events )
1245*0Sstevel@tonic-gate != events ) {
1246*0Sstevel@tonic-gate pip->ossi_pollfds[ i ].events |= events;
1247*0Sstevel@tonic-gate return( 1 );
1248*0Sstevel@tonic-gate } else {
1249*0Sstevel@tonic-gate return( 0 );
1250*0Sstevel@tonic-gate }
1251*0Sstevel@tonic-gate }
1252*0Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].fd == -1 && openslot == -1 ) {
1253*0Sstevel@tonic-gate openslot = i; /* remember for later */
1254*0Sstevel@tonic-gate }
1255*0Sstevel@tonic-gate }
1256*0Sstevel@tonic-gate
1257*0Sstevel@tonic-gate /*
1258*0Sstevel@tonic-gate * "fd" is not currently being poll'd on -- add to array.
1259*0Sstevel@tonic-gate * if we need to expand the pollfds array, we do it in increments of
1260*0Sstevel@tonic-gate * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
1261*0Sstevel@tonic-gate */
1262*0Sstevel@tonic-gate if ( openslot == -1 ) {
1263*0Sstevel@tonic-gate struct pollfd *newpollfds;
1264*0Sstevel@tonic-gate
1265*0Sstevel@tonic-gate if ( pip->ossi_pollfds_size == 0 ) {
1266*0Sstevel@tonic-gate newpollfds = (struct pollfd *)NSLDAPI_MALLOC(
1267*0Sstevel@tonic-gate NSLDAPI_POLL_ARRAY_GROWTH
1268*0Sstevel@tonic-gate * sizeof( struct pollfd ));
1269*0Sstevel@tonic-gate } else {
1270*0Sstevel@tonic-gate newpollfds = (struct pollfd *)NSLDAPI_REALLOC(
1271*0Sstevel@tonic-gate pip->ossi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
1272*0Sstevel@tonic-gate + pip->ossi_pollfds_size)
1273*0Sstevel@tonic-gate * sizeof( struct pollfd ));
1274*0Sstevel@tonic-gate }
1275*0Sstevel@tonic-gate if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
1276*0Sstevel@tonic-gate return( 0 );
1277*0Sstevel@tonic-gate }
1278*0Sstevel@tonic-gate pip->ossi_pollfds = newpollfds;
1279*0Sstevel@tonic-gate openslot = pip->ossi_pollfds_size;
1280*0Sstevel@tonic-gate pip->ossi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
1281*0Sstevel@tonic-gate for ( i = openslot + 1; i < pip->ossi_pollfds_size; ++i ) {
1282*0Sstevel@tonic-gate pip->ossi_pollfds[ i ].fd = -1;
1283*0Sstevel@tonic-gate pip->ossi_pollfds[ i ].events =
1284*0Sstevel@tonic-gate pip->ossi_pollfds[ i ].revents = 0;
1285*0Sstevel@tonic-gate }
1286*0Sstevel@tonic-gate }
1287*0Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].fd = fd;
1288*0Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].events = events;
1289*0Sstevel@tonic-gate pip->ossi_pollfds[ openslot ].revents = 0;
1290*0Sstevel@tonic-gate return( 1 );
1291*0Sstevel@tonic-gate }
1292*0Sstevel@tonic-gate
1293*0Sstevel@tonic-gate
1294*0Sstevel@tonic-gate /*
1295*0Sstevel@tonic-gate * returns 1 if any "events" from "fd" were removed from pollfds
1296*0Sstevel@tonic-gate * returns 0 of "fd" wasn't in pollfds or if events did not overlap.
1297*0Sstevel@tonic-gate */
1298*0Sstevel@tonic-gate static int
1299*0Sstevel@tonic-gate nsldapi_clear_from_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1300*0Sstevel@tonic-gate short events )
1301*0Sstevel@tonic-gate {
1302*0Sstevel@tonic-gate int i;
1303*0Sstevel@tonic-gate
1304*0Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1305*0Sstevel@tonic-gate if ( pip->ossi_pollfds[i].fd == fd ) {
1306*0Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].events & events ) != 0 ) {
1307*0Sstevel@tonic-gate pip->ossi_pollfds[ i ].events &= ~events;
1308*0Sstevel@tonic-gate if ( pip->ossi_pollfds[ i ].events == 0 ) {
1309*0Sstevel@tonic-gate pip->ossi_pollfds[i].fd = -1;
1310*0Sstevel@tonic-gate }
1311*0Sstevel@tonic-gate return( 1 ); /* events overlap */
1312*0Sstevel@tonic-gate } else {
1313*0Sstevel@tonic-gate return( 0 ); /* events do not overlap */
1314*0Sstevel@tonic-gate }
1315*0Sstevel@tonic-gate }
1316*0Sstevel@tonic-gate }
1317*0Sstevel@tonic-gate
1318*0Sstevel@tonic-gate return( 0 ); /* "fd" was not found */
1319*0Sstevel@tonic-gate }
1320*0Sstevel@tonic-gate
1321*0Sstevel@tonic-gate
1322*0Sstevel@tonic-gate /*
1323*0Sstevel@tonic-gate * returns 1 if any "revents" from "fd" were set in pollfds revents field.
1324*0Sstevel@tonic-gate * returns 0 if not.
1325*0Sstevel@tonic-gate */
1326*0Sstevel@tonic-gate static int
1327*0Sstevel@tonic-gate nsldapi_find_in_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1328*0Sstevel@tonic-gate short revents )
1329*0Sstevel@tonic-gate {
1330*0Sstevel@tonic-gate int i;
1331*0Sstevel@tonic-gate
1332*0Sstevel@tonic-gate for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1333*0Sstevel@tonic-gate if ( pip->ossi_pollfds[i].fd == fd ) {
1334*0Sstevel@tonic-gate if (( pip->ossi_pollfds[ i ].revents & revents ) != 0 ) {
1335*0Sstevel@tonic-gate return( 1 ); /* revents overlap */
1336*0Sstevel@tonic-gate } else {
1337*0Sstevel@tonic-gate return( 0 ); /* revents do not overlap */
1338*0Sstevel@tonic-gate }
1339*0Sstevel@tonic-gate }
1340*0Sstevel@tonic-gate }
1341*0Sstevel@tonic-gate
1342*0Sstevel@tonic-gate return( 0 ); /* "fd" was not found */
1343*0Sstevel@tonic-gate }
1344*0Sstevel@tonic-gate #endif /* NSLDAPI_HAVE_POLL */
1345*0Sstevel@tonic-gate
1346*0Sstevel@tonic-gate
1347*0Sstevel@tonic-gate /*
1348*0Sstevel@tonic-gate * returns 1 if "sb" was added to pollfds.
1349*0Sstevel@tonic-gate * returns 1 if some of the bits in "events" were added to pollfds.
1350*0Sstevel@tonic-gate * returns 0 if no changes were made.
1351*0Sstevel@tonic-gate */
1352*0Sstevel@tonic-gate static int
1353*0Sstevel@tonic-gate nsldapi_add_to_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
1354*0Sstevel@tonic-gate short events )
1355*0Sstevel@tonic-gate {
1356*0Sstevel@tonic-gate int i, openslot;
1357*0Sstevel@tonic-gate
1358*0Sstevel@tonic-gate /* first we check to see if "sb" is already in our pollfds */
1359*0Sstevel@tonic-gate openslot = -1;
1360*0Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1361*0Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1362*0Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_events & events )
1363*0Sstevel@tonic-gate != events ) {
1364*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events |= events;
1365*0Sstevel@tonic-gate return( 1 );
1366*0Sstevel@tonic-gate } else {
1367*0Sstevel@tonic-gate return( 0 );
1368*0Sstevel@tonic-gate }
1369*0Sstevel@tonic-gate }
1370*0Sstevel@tonic-gate if ( pip->cbsi_pollfds[ i ].lpoll_fd == -1 && openslot == -1 ) {
1371*0Sstevel@tonic-gate openslot = i; /* remember for later */
1372*0Sstevel@tonic-gate }
1373*0Sstevel@tonic-gate }
1374*0Sstevel@tonic-gate
1375*0Sstevel@tonic-gate /*
1376*0Sstevel@tonic-gate * "sb" is not currently being poll'd on -- add to array.
1377*0Sstevel@tonic-gate * if we need to expand the pollfds array, we do it in increments of
1378*0Sstevel@tonic-gate * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
1379*0Sstevel@tonic-gate */
1380*0Sstevel@tonic-gate if ( openslot == -1 ) {
1381*0Sstevel@tonic-gate LDAP_X_PollFD *newpollfds;
1382*0Sstevel@tonic-gate
1383*0Sstevel@tonic-gate if ( pip->cbsi_pollfds_size == 0 ) {
1384*0Sstevel@tonic-gate newpollfds = (LDAP_X_PollFD *)NSLDAPI_MALLOC(
1385*0Sstevel@tonic-gate NSLDAPI_POLL_ARRAY_GROWTH
1386*0Sstevel@tonic-gate * sizeof( LDAP_X_PollFD ));
1387*0Sstevel@tonic-gate } else {
1388*0Sstevel@tonic-gate newpollfds = (LDAP_X_PollFD *)NSLDAPI_REALLOC(
1389*0Sstevel@tonic-gate pip->cbsi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
1390*0Sstevel@tonic-gate + pip->cbsi_pollfds_size)
1391*0Sstevel@tonic-gate * sizeof( LDAP_X_PollFD ));
1392*0Sstevel@tonic-gate }
1393*0Sstevel@tonic-gate if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
1394*0Sstevel@tonic-gate return( 0 );
1395*0Sstevel@tonic-gate }
1396*0Sstevel@tonic-gate pip->cbsi_pollfds = newpollfds;
1397*0Sstevel@tonic-gate openslot = pip->cbsi_pollfds_size;
1398*0Sstevel@tonic-gate pip->cbsi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
1399*0Sstevel@tonic-gate for ( i = openslot + 1; i < pip->cbsi_pollfds_size; ++i ) {
1400*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_fd = -1;
1401*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_socketarg = NULL;
1402*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events =
1403*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_revents = 0;
1404*0Sstevel@tonic-gate }
1405*0Sstevel@tonic-gate }
1406*0Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_fd = sb->sb_sd;
1407*0Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_socketarg =
1408*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg;
1409*0Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_events = events;
1410*0Sstevel@tonic-gate pip->cbsi_pollfds[ openslot ].lpoll_revents = 0;
1411*0Sstevel@tonic-gate return( 1 );
1412*0Sstevel@tonic-gate }
1413*0Sstevel@tonic-gate
1414*0Sstevel@tonic-gate
1415*0Sstevel@tonic-gate /*
1416*0Sstevel@tonic-gate * returns 1 if any "events" from "sb" were removed from pollfds
1417*0Sstevel@tonic-gate * returns 0 of "sb" wasn't in pollfds or if events did not overlap.
1418*0Sstevel@tonic-gate */
1419*0Sstevel@tonic-gate static int
1420*0Sstevel@tonic-gate nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
1421*0Sstevel@tonic-gate struct nsldapi_cb_statusinfo *pip, short events )
1422*0Sstevel@tonic-gate {
1423*0Sstevel@tonic-gate int i;
1424*0Sstevel@tonic-gate
1425*0Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1426*0Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1427*0Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_events
1428*0Sstevel@tonic-gate & events ) != 0 ) {
1429*0Sstevel@tonic-gate pip->cbsi_pollfds[ i ].lpoll_events &= ~events;
1430*0Sstevel@tonic-gate if ( pip->cbsi_pollfds[ i ].lpoll_events
1431*0Sstevel@tonic-gate == 0 ) {
1432*0Sstevel@tonic-gate pip->cbsi_pollfds[i].lpoll_fd = -1;
1433*0Sstevel@tonic-gate }
1434*0Sstevel@tonic-gate return( 1 ); /* events overlap */
1435*0Sstevel@tonic-gate } else {
1436*0Sstevel@tonic-gate return( 0 ); /* events do not overlap */
1437*0Sstevel@tonic-gate }
1438*0Sstevel@tonic-gate }
1439*0Sstevel@tonic-gate }
1440*0Sstevel@tonic-gate
1441*0Sstevel@tonic-gate return( 0 ); /* "sb" was not found */
1442*0Sstevel@tonic-gate }
1443*0Sstevel@tonic-gate
1444*0Sstevel@tonic-gate
1445*0Sstevel@tonic-gate /*
1446*0Sstevel@tonic-gate * returns 1 if any "revents" from "sb" were set in pollfds revents field.
1447*0Sstevel@tonic-gate * returns 0 if not.
1448*0Sstevel@tonic-gate */
1449*0Sstevel@tonic-gate static int
1450*0Sstevel@tonic-gate nsldapi_find_in_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
1451*0Sstevel@tonic-gate short revents )
1452*0Sstevel@tonic-gate {
1453*0Sstevel@tonic-gate int i;
1454*0Sstevel@tonic-gate
1455*0Sstevel@tonic-gate for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1456*0Sstevel@tonic-gate if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1457*0Sstevel@tonic-gate if (( pip->cbsi_pollfds[ i ].lpoll_revents
1458*0Sstevel@tonic-gate & revents ) != 0 ) {
1459*0Sstevel@tonic-gate return( 1 ); /* revents overlap */
1460*0Sstevel@tonic-gate } else {
1461*0Sstevel@tonic-gate return( 0 ); /* revents do not overlap */
1462*0Sstevel@tonic-gate }
1463*0Sstevel@tonic-gate }
1464*0Sstevel@tonic-gate }
1465*0Sstevel@tonic-gate
1466*0Sstevel@tonic-gate return( 0 ); /* "sb" was not found */
1467*0Sstevel@tonic-gate }
1468*0Sstevel@tonic-gate
1469*0Sstevel@tonic-gate
1470*0Sstevel@tonic-gate /*
1471*0Sstevel@tonic-gate * Install read and write functions into lber layer / sb
1472*0Sstevel@tonic-gate */
1473*0Sstevel@tonic-gate int
1474*0Sstevel@tonic-gate nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb )
1475*0Sstevel@tonic-gate {
1476*0Sstevel@tonic-gate struct lber_x_ext_io_fns lberiofns;
1477*0Sstevel@tonic-gate
1478*0Sstevel@tonic-gate memset( &lberiofns, 0, sizeof(struct lber_x_ext_io_fns) );
1479*0Sstevel@tonic-gate if ( NULL != sb ) {
1480*0Sstevel@tonic-gate lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
1481*0Sstevel@tonic-gate lberiofns.lbextiofn_read = ld->ld_extread_fn;
1482*0Sstevel@tonic-gate lberiofns.lbextiofn_write = ld->ld_extwrite_fn;
1483*0Sstevel@tonic-gate lberiofns.lbextiofn_writev = ld->ld_extwritev_fn;
1484*0Sstevel@tonic-gate lberiofns.lbextiofn_socket_arg = ld->ld_ext_session_arg;
1485*0Sstevel@tonic-gate
1486*0Sstevel@tonic-gate if ( ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS,
1487*0Sstevel@tonic-gate &lberiofns ) != 0 ) {
1488*0Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
1489*0Sstevel@tonic-gate }
1490*0Sstevel@tonic-gate }
1491*0Sstevel@tonic-gate
1492*0Sstevel@tonic-gate return( LDAP_SUCCESS );
1493*0Sstevel@tonic-gate }
1494*0Sstevel@tonic-gate
1495*0Sstevel@tonic-gate
1496*0Sstevel@tonic-gate /*
1497*0Sstevel@tonic-gate ******************************************************************************
1498*0Sstevel@tonic-gate * One struct and several functions to bridge the gap between new extended
1499*0Sstevel@tonic-gate * I/O functions that are installed using ldap_set_option( ...,
1500*0Sstevel@tonic-gate * LDAP_OPT_EXTIO_FN_PTRS, ... ) and the original "classic" I/O functions
1501*0Sstevel@tonic-gate * (installed using LDAP_OPT_IO_FN_PTRS) follow.
1502*0Sstevel@tonic-gate *
1503*0Sstevel@tonic-gate * Our basic strategy is to use the new extended arg to hold a pointer to a
1504*0Sstevel@tonic-gate * structure that contains a pointer to the LDAP * (which contains pointers
1505*0Sstevel@tonic-gate * to the old functions so we can call them) as well as a pointer to an
1506*0Sstevel@tonic-gate * LBER_SOCKET to hold the socket used by the classic functions (the new
1507*0Sstevel@tonic-gate * functions use a simple int for the socket).
1508*0Sstevel@tonic-gate */
1509*0Sstevel@tonic-gate typedef struct nsldapi_compat_socket_info {
1510*0Sstevel@tonic-gate LBER_SOCKET csi_socket;
1511*0Sstevel@tonic-gate LDAP *csi_ld;
1512*0Sstevel@tonic-gate } NSLDAPICompatSocketInfo;
1513*0Sstevel@tonic-gate
1514*0Sstevel@tonic-gate static int LDAP_CALLBACK
1515*0Sstevel@tonic-gate nsldapi_ext_compat_read( int s, void *buf, int len,
1516*0Sstevel@tonic-gate struct lextiof_socket_private *arg )
1517*0Sstevel@tonic-gate {
1518*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1519*0Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1520*0Sstevel@tonic-gate
1521*0Sstevel@tonic-gate return( iofns->liof_read( csip->csi_socket, buf, len ));
1522*0Sstevel@tonic-gate }
1523*0Sstevel@tonic-gate
1524*0Sstevel@tonic-gate
1525*0Sstevel@tonic-gate static int LDAP_CALLBACK
1526*0Sstevel@tonic-gate nsldapi_ext_compat_write( int s, const void *buf, int len,
1527*0Sstevel@tonic-gate struct lextiof_socket_private *arg )
1528*0Sstevel@tonic-gate {
1529*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1530*0Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1531*0Sstevel@tonic-gate
1532*0Sstevel@tonic-gate return( iofns->liof_write( csip->csi_socket, buf, len ));
1533*0Sstevel@tonic-gate }
1534*0Sstevel@tonic-gate
1535*0Sstevel@tonic-gate
1536*0Sstevel@tonic-gate static int LDAP_CALLBACK
1537*0Sstevel@tonic-gate nsldapi_ext_compat_poll( LDAP_X_PollFD fds[], int nfds, int timeout,
1538*0Sstevel@tonic-gate struct lextiof_session_private *arg )
1539*0Sstevel@tonic-gate {
1540*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1541*0Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1542*0Sstevel@tonic-gate fd_set readfds, writefds;
1543*0Sstevel@tonic-gate int i, rc, maxfd = 0;
1544*0Sstevel@tonic-gate struct timeval tv, *tvp;
1545*0Sstevel@tonic-gate
1546*0Sstevel@tonic-gate /*
1547*0Sstevel@tonic-gate * Prepare fd_sets for select()
1548*0Sstevel@tonic-gate */
1549*0Sstevel@tonic-gate FD_ZERO( &readfds );
1550*0Sstevel@tonic-gate FD_ZERO( &writefds );
1551*0Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) {
1552*0Sstevel@tonic-gate if ( fds[ i ].lpoll_fd < 0 ) {
1553*0Sstevel@tonic-gate continue;
1554*0Sstevel@tonic-gate }
1555*0Sstevel@tonic-gate
1556*0Sstevel@tonic-gate if ( fds[ i ].lpoll_fd >= FD_SETSIZE ) {
1557*0Sstevel@tonic-gate LDAP_SET_ERRNO( csip->csi_ld, EINVAL );
1558*0Sstevel@tonic-gate return( -1 );
1559*0Sstevel@tonic-gate }
1560*0Sstevel@tonic-gate
1561*0Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )) {
1562*0Sstevel@tonic-gate FD_SET( fds[i].lpoll_fd, &readfds );
1563*0Sstevel@tonic-gate }
1564*0Sstevel@tonic-gate
1565*0Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )) {
1566*0Sstevel@tonic-gate FD_SET( fds[i].lpoll_fd, &writefds );
1567*0Sstevel@tonic-gate }
1568*0Sstevel@tonic-gate
1569*0Sstevel@tonic-gate fds[i].lpoll_revents = 0; /* clear revents */
1570*0Sstevel@tonic-gate
1571*0Sstevel@tonic-gate if ( fds[i].lpoll_fd >= maxfd ) {
1572*0Sstevel@tonic-gate maxfd = fds[i].lpoll_fd;
1573*0Sstevel@tonic-gate }
1574*0Sstevel@tonic-gate }
1575*0Sstevel@tonic-gate
1576*0Sstevel@tonic-gate /*
1577*0Sstevel@tonic-gate * select() using callback.
1578*0Sstevel@tonic-gate */
1579*0Sstevel@tonic-gate ++maxfd;
1580*0Sstevel@tonic-gate if ( timeout == -1 ) {
1581*0Sstevel@tonic-gate tvp = NULL;
1582*0Sstevel@tonic-gate } else {
1583*0Sstevel@tonic-gate tv.tv_sec = timeout / 1000;
1584*0Sstevel@tonic-gate tv.tv_usec = 1000 * ( timeout - tv.tv_sec * 1000 );
1585*0Sstevel@tonic-gate tvp = &tv;
1586*0Sstevel@tonic-gate }
1587*0Sstevel@tonic-gate rc = iofns->liof_select( maxfd, &readfds, &writefds, NULL, tvp );
1588*0Sstevel@tonic-gate if ( rc <= 0 ) { /* timeout or fatal error */
1589*0Sstevel@tonic-gate return( rc );
1590*0Sstevel@tonic-gate }
1591*0Sstevel@tonic-gate
1592*0Sstevel@tonic-gate /*
1593*0Sstevel@tonic-gate * Use info. in fd_sets to populate poll() revents.
1594*0Sstevel@tonic-gate */
1595*0Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) {
1596*0Sstevel@tonic-gate if ( fds[ i ].lpoll_fd < 0 ) {
1597*0Sstevel@tonic-gate continue;
1598*0Sstevel@tonic-gate }
1599*0Sstevel@tonic-gate
1600*0Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )
1601*0Sstevel@tonic-gate && FD_ISSET( fds[i].lpoll_fd, &readfds )) {
1602*0Sstevel@tonic-gate fds[i].lpoll_revents |= LDAP_X_POLLIN;
1603*0Sstevel@tonic-gate }
1604*0Sstevel@tonic-gate
1605*0Sstevel@tonic-gate if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )
1606*0Sstevel@tonic-gate && FD_ISSET( fds[i].lpoll_fd, &writefds )) {
1607*0Sstevel@tonic-gate fds[i].lpoll_revents |= LDAP_X_POLLOUT;
1608*0Sstevel@tonic-gate }
1609*0Sstevel@tonic-gate
1610*0Sstevel@tonic-gate /* XXXmcs: any other cases to deal with? LDAP_X_POLLERR? */
1611*0Sstevel@tonic-gate }
1612*0Sstevel@tonic-gate
1613*0Sstevel@tonic-gate return( rc );
1614*0Sstevel@tonic-gate }
1615*0Sstevel@tonic-gate
1616*0Sstevel@tonic-gate
1617*0Sstevel@tonic-gate static LBER_SOCKET
1618*0Sstevel@tonic-gate nsldapi_compat_socket( LDAP *ld, int secure, int domain, int type,
1619*0Sstevel@tonic-gate int protocol )
1620*0Sstevel@tonic-gate {
1621*0Sstevel@tonic-gate int s;
1622*0Sstevel@tonic-gate
1623*0Sstevel@tonic-gate s = ld->ld_io_fns_ptr->liof_socket( domain, type, protocol );
1624*0Sstevel@tonic-gate
1625*0Sstevel@tonic-gate if ( s >= 0 ) {
1626*0Sstevel@tonic-gate char *errmsg = NULL;
1627*0Sstevel@tonic-gate
1628*0Sstevel@tonic-gate #ifdef NSLDAPI_HAVE_POLL
1629*0Sstevel@tonic-gate if ( ld->ld_io_fns_ptr->liof_select != NULL
1630*0Sstevel@tonic-gate && s >= FD_SETSIZE ) {
1631*0Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN,
1632*0Sstevel@tonic-gate "can't use socket >= FD_SETSIZE");
1633*0Sstevel@tonic-gate }
1634*0Sstevel@tonic-gate #elif !defined(_WINDOWS) /* not on Windows and do not have poll() */
1635*0Sstevel@tonic-gate if ( s >= FD_SETSIZE ) {
1636*0Sstevel@tonic-gate errmsg = "can't use socket >= FD_SETSIZE";
1637*0Sstevel@tonic-gate }
1638*0Sstevel@tonic-gate #endif
1639*0Sstevel@tonic-gate
1640*0Sstevel@tonic-gate if ( NULL == errmsg && secure &&
1641*0Sstevel@tonic-gate ld->ld_io_fns_ptr->liof_ssl_enable( s ) < 0 ) {
1642*0Sstevel@tonic-gate errmsg = dgettext(TEXT_DOMAIN,
1643*0Sstevel@tonic-gate "failed to enable secure mode");
1644*0Sstevel@tonic-gate }
1645*0Sstevel@tonic-gate
1646*0Sstevel@tonic-gate if ( NULL != errmsg ) {
1647*0Sstevel@tonic-gate if ( NULL == ld->ld_io_fns_ptr->liof_close ) {
1648*0Sstevel@tonic-gate nsldapi_os_closesocket( s );
1649*0Sstevel@tonic-gate } else {
1650*0Sstevel@tonic-gate ld->ld_io_fns_ptr->liof_close( s );
1651*0Sstevel@tonic-gate }
1652*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
1653*0Sstevel@tonic-gate nsldapi_strdup( errmsg ));
1654*0Sstevel@tonic-gate return( -1 );
1655*0Sstevel@tonic-gate }
1656*0Sstevel@tonic-gate }
1657*0Sstevel@tonic-gate
1658*0Sstevel@tonic-gate return( s );
1659*0Sstevel@tonic-gate }
1660*0Sstevel@tonic-gate
1661*0Sstevel@tonic-gate
1662*0Sstevel@tonic-gate /*
1663*0Sstevel@tonic-gate * Note: timeout is ignored because we have no way to pass it via
1664*0Sstevel@tonic-gate * the old I/O callback interface.
1665*0Sstevel@tonic-gate */
1666*0Sstevel@tonic-gate static int LDAP_CALLBACK
1667*0Sstevel@tonic-gate nsldapi_ext_compat_connect( const char *hostlist, int defport, int timeout,
1668*0Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg,
1669*0Sstevel@tonic-gate struct lextiof_socket_private **socketargp
1670*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1671*0Sstevel@tonic-gate , void **not_used )
1672*0Sstevel@tonic-gate #else
1673*0Sstevel@tonic-gate )
1674*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
1675*0Sstevel@tonic-gate {
1676*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *defcsip;
1677*0Sstevel@tonic-gate struct ldap_io_fns *iofns;
1678*0Sstevel@tonic-gate int s, secure;
1679*0Sstevel@tonic-gate NSLDAPI_SOCKET_FN *socketfn;
1680*0Sstevel@tonic-gate NSLDAPI_IOCTL_FN *ioctlfn;
1681*0Sstevel@tonic-gate NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn;
1682*0Sstevel@tonic-gate NSLDAPI_CONNECT_FN *connectfn;
1683*0Sstevel@tonic-gate NSLDAPI_CLOSE_FN *closefn;
1684*0Sstevel@tonic-gate
1685*0Sstevel@tonic-gate defcsip = (NSLDAPICompatSocketInfo *)sessionarg;
1686*0Sstevel@tonic-gate iofns = defcsip->csi_ld->ld_io_fns_ptr;
1687*0Sstevel@tonic-gate
1688*0Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
1689*0Sstevel@tonic-gate if ( NULL == iofns->liof_ssl_enable ) {
1690*0Sstevel@tonic-gate LDAP_SET_ERRNO( defcsip->csi_ld, EINVAL );
1691*0Sstevel@tonic-gate return( -1 );
1692*0Sstevel@tonic-gate }
1693*0Sstevel@tonic-gate secure = 1;
1694*0Sstevel@tonic-gate } else {
1695*0Sstevel@tonic-gate secure = 0;
1696*0Sstevel@tonic-gate }
1697*0Sstevel@tonic-gate
1698*0Sstevel@tonic-gate socketfn = ( iofns->liof_socket == NULL ) ?
1699*0Sstevel@tonic-gate nsldapi_os_socket : nsldapi_compat_socket;
1700*0Sstevel@tonic-gate ioctlfn = ( iofns->liof_ioctl == NULL ) ?
1701*0Sstevel@tonic-gate nsldapi_os_ioctl : (NSLDAPI_IOCTL_FN *)(iofns->liof_ioctl);
1702*0Sstevel@tonic-gate if ( NULL == iofns->liof_connect ) {
1703*0Sstevel@tonic-gate connectwithtofn = nsldapi_os_connect_with_to;
1704*0Sstevel@tonic-gate connectfn = NULL;
1705*0Sstevel@tonic-gate } else {
1706*0Sstevel@tonic-gate connectwithtofn = NULL;
1707*0Sstevel@tonic-gate connectfn = iofns->liof_connect;
1708*0Sstevel@tonic-gate }
1709*0Sstevel@tonic-gate closefn = ( iofns->liof_close == NULL ) ?
1710*0Sstevel@tonic-gate nsldapi_os_closesocket : iofns->liof_close;
1711*0Sstevel@tonic-gate
1712*0Sstevel@tonic-gate s = nsldapi_try_each_host( defcsip->csi_ld, hostlist, defport,
1713*0Sstevel@tonic-gate secure, socketfn, ioctlfn, connectwithtofn,
1714*0Sstevel@tonic-gate connectfn, closefn );
1715*0Sstevel@tonic-gate
1716*0Sstevel@tonic-gate if ( s >= 0 ) {
1717*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip;
1718*0Sstevel@tonic-gate
1719*0Sstevel@tonic-gate if (( csip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
1720*0Sstevel@tonic-gate sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
1721*0Sstevel@tonic-gate (*closefn)( s );
1722*0Sstevel@tonic-gate LDAP_SET_LDERRNO( defcsip->csi_ld, LDAP_NO_MEMORY,
1723*0Sstevel@tonic-gate NULL, NULL );
1724*0Sstevel@tonic-gate return( -1 );
1725*0Sstevel@tonic-gate }
1726*0Sstevel@tonic-gate
1727*0Sstevel@tonic-gate csip->csi_socket = s;
1728*0Sstevel@tonic-gate csip->csi_ld = defcsip->csi_ld;
1729*0Sstevel@tonic-gate *socketargp = (void *)csip;
1730*0Sstevel@tonic-gate
1731*0Sstevel@tonic-gate /*
1732*0Sstevel@tonic-gate * We always return 1, which is a valid but not unique socket
1733*0Sstevel@tonic-gate * (file descriptor) number. The extended I/O functions only
1734*0Sstevel@tonic-gate * require that the combination of the void *arg and the int
1735*0Sstevel@tonic-gate * socket be unique. Since we allocate the
1736*0Sstevel@tonic-gate * NSLDAPICompatSocketInfo that we assign to arg, we meet
1737*0Sstevel@tonic-gate * that requirement.
1738*0Sstevel@tonic-gate */
1739*0Sstevel@tonic-gate s = 1;
1740*0Sstevel@tonic-gate }
1741*0Sstevel@tonic-gate
1742*0Sstevel@tonic-gate return( s );
1743*0Sstevel@tonic-gate }
1744*0Sstevel@tonic-gate
1745*0Sstevel@tonic-gate
1746*0Sstevel@tonic-gate static int LDAP_CALLBACK
1747*0Sstevel@tonic-gate nsldapi_ext_compat_close( int s, struct lextiof_socket_private *arg )
1748*0Sstevel@tonic-gate {
1749*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1750*0Sstevel@tonic-gate struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1751*0Sstevel@tonic-gate int rc;
1752*0Sstevel@tonic-gate
1753*0Sstevel@tonic-gate rc = iofns->liof_close( csip->csi_socket );
1754*0Sstevel@tonic-gate
1755*0Sstevel@tonic-gate NSLDAPI_FREE( csip );
1756*0Sstevel@tonic-gate
1757*0Sstevel@tonic-gate return( rc );
1758*0Sstevel@tonic-gate }
1759*0Sstevel@tonic-gate
1760*0Sstevel@tonic-gate /*
1761*0Sstevel@tonic-gate * Install the I/O functions.
1762*0Sstevel@tonic-gate * Return an LDAP error code (LDAP_SUCCESS if all goes well).
1763*0Sstevel@tonic-gate */
1764*0Sstevel@tonic-gate int
1765*0Sstevel@tonic-gate nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns )
1766*0Sstevel@tonic-gate {
1767*0Sstevel@tonic-gate NSLDAPICompatSocketInfo *defcsip;
1768*0Sstevel@tonic-gate
1769*0Sstevel@tonic-gate if (( defcsip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
1770*0Sstevel@tonic-gate sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
1771*0Sstevel@tonic-gate return( LDAP_NO_MEMORY );
1772*0Sstevel@tonic-gate }
1773*0Sstevel@tonic-gate
1774*0Sstevel@tonic-gate defcsip->csi_socket = -1;
1775*0Sstevel@tonic-gate defcsip->csi_ld = ld;
1776*0Sstevel@tonic-gate
1777*0Sstevel@tonic-gate if ( ld->ld_io_fns_ptr != NULL ) {
1778*0Sstevel@tonic-gate (void)memset( (char *)ld->ld_io_fns_ptr, 0,
1779*0Sstevel@tonic-gate sizeof( struct ldap_io_fns ));
1780*0Sstevel@tonic-gate } else if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_CALLOC(
1781*0Sstevel@tonic-gate 1, sizeof( struct ldap_io_fns ))) == NULL ) {
1782*0Sstevel@tonic-gate NSLDAPI_FREE( defcsip );
1783*0Sstevel@tonic-gate return( LDAP_NO_MEMORY );
1784*0Sstevel@tonic-gate }
1785*0Sstevel@tonic-gate
1786*0Sstevel@tonic-gate /* struct copy */
1787*0Sstevel@tonic-gate *(ld->ld_io_fns_ptr) = *iofns;
1788*0Sstevel@tonic-gate
1789*0Sstevel@tonic-gate ld->ld_extio_size = LBER_X_EXTIO_FNS_SIZE;
1790*0Sstevel@tonic-gate ld->ld_ext_session_arg = defcsip;
1791*0Sstevel@tonic-gate ld->ld_extread_fn = nsldapi_ext_compat_read;
1792*0Sstevel@tonic-gate ld->ld_extwrite_fn = nsldapi_ext_compat_write;
1793*0Sstevel@tonic-gate ld->ld_extpoll_fn = nsldapi_ext_compat_poll;
1794*0Sstevel@tonic-gate ld->ld_extconnect_fn = nsldapi_ext_compat_connect;
1795*0Sstevel@tonic-gate ld->ld_extclose_fn = nsldapi_ext_compat_close;
1796*0Sstevel@tonic-gate
1797*0Sstevel@tonic-gate return( nsldapi_install_lber_extiofns( ld, ld->ld_sbp ));
1798*0Sstevel@tonic-gate }
1799*0Sstevel@tonic-gate /*
1800*0Sstevel@tonic-gate * end of compat I/O functions
1801*0Sstevel@tonic-gate ******************************************************************************
1802*0Sstevel@tonic-gate */
1803*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1804*0Sstevel@tonic-gate /*
1805*0Sstevel@tonic-gate * _ns_gethostbyaddr is a helper function for the ssl layer so that
1806*0Sstevel@tonic-gate * it can use the ldap layer's gethostbyaddr resolver.
1807*0Sstevel@tonic-gate */
1808*0Sstevel@tonic-gate
1809*0Sstevel@tonic-gate LDAPHostEnt *
1810*0Sstevel@tonic-gate _ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type,
1811*0Sstevel@tonic-gate LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
1812*0Sstevel@tonic-gate void *extradata)
1813*0Sstevel@tonic-gate {
1814*0Sstevel@tonic-gate if (ld == NULL || ld->ld_dns_gethostbyaddr_fn == NULL)
1815*0Sstevel@tonic-gate return (NULL);
1816*0Sstevel@tonic-gate return (ld->ld_dns_gethostbyaddr_fn(addr, length, type,
1817*0Sstevel@tonic-gate result, buffer, buflen, statusp, extradata));
1818*0Sstevel@tonic-gate }
1819*0Sstevel@tonic-gate
1820*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */
1821*0Sstevel@tonic-gate
1822*0Sstevel@tonic-gate
1823