1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
11*7c478bd9Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
12*7c478bd9Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
13*7c478bd9Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
16*7c478bd9Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17*7c478bd9Sstevel@tonic-gate  * implied. See the License for the specific language governing
18*7c478bd9Sstevel@tonic-gate  * rights and limitations under the License.
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
21*7c478bd9Sstevel@tonic-gate  * March 31, 1998.
22*7c478bd9Sstevel@tonic-gate  *
23*7c478bd9Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
24*7c478bd9Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
25*7c478bd9Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
26*7c478bd9Sstevel@tonic-gate  * Rights Reserved.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * Contributor(s):
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * Extended I/O callback functions for libldap that use
33*7c478bd9Sstevel@tonic-gate  * NSPR (Netscape Portable Runtime) I/O.
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * High level strategy: we use the socket-specific arg to hold our own data
36*7c478bd9Sstevel@tonic-gate  * structure that includes the NSPR file handle (PRFileDesc *), among other
37*7c478bd9Sstevel@tonic-gate  * useful information.  We use the default argument to hold an LDAP session
38*7c478bd9Sstevel@tonic-gate  * handle specific data structure.
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "ldappr-int.h"
42*7c478bd9Sstevel@tonic-gate #include <string.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #define PRLDAP_POLL_ARRAY_GROWTH  5  /* grow arrays 5 elements at a time */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  * Local function prototypes:
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout );
50*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize,
51*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
52*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len,
53*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
54*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds,
55*7c478bd9Sstevel@tonic-gate 	int timeout, struct lextiof_session_private *sessionarg );
56*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_connect( const char *hostlist, int defport,
57*7c478bd9Sstevel@tonic-gate 	int timeout, unsigned long options,
58*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg,
59*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private **socketargp
60*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
61*7c478bd9Sstevel@tonic-gate 	, void **dhost );
62*7c478bd9Sstevel@tonic-gate #else
63*7c478bd9Sstevel@tonic-gate 	);
64*7c478bd9Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
65*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_close( int s,
66*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
67*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_newhandle( LDAP *ld,
68*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
69*7c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld,
70*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
71*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld,
72*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
73*7c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld,
74*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
75*7c478bd9Sstevel@tonic-gate static PRLDAPIOSessionArg *prldap_session_arg_alloc( void );
76*7c478bd9Sstevel@tonic-gate static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp );
77*7c478bd9Sstevel@tonic-gate static PRLDAPIOSocketArg *prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg );
78*7c478bd9Sstevel@tonic-gate static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp );
79*7c478bd9Sstevel@tonic-gate static void *prldap_safe_realloc( void *ptr, PRUint32 size );
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /*
84*7c478bd9Sstevel@tonic-gate  * Local macros:
85*7c478bd9Sstevel@tonic-gate  */
86*7c478bd9Sstevel@tonic-gate /* given a socket-specific arg, return the corresponding PRFileDesc * */
87*7c478bd9Sstevel@tonic-gate #define PRLDAP_GET_PRFD( socketarg )	\
88*7c478bd9Sstevel@tonic-gate 		(((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd)
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate /*
91*7c478bd9Sstevel@tonic-gate  * Static variables.
92*7c478bd9Sstevel@tonic-gate  */
93*7c478bd9Sstevel@tonic-gate static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate  * Install NSPR I/O functions into ld (if ld is NULL, they are installed
97*7c478bd9Sstevel@tonic-gate  * as the default functions for new LDAP * handles).
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  * Returns 0 if all goes well and -1 if not.
100*7c478bd9Sstevel@tonic-gate  */
101*7c478bd9Sstevel@tonic-gate int
102*7c478bd9Sstevel@tonic-gate prldap_install_io_functions( LDAP *ld, int shared )
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate     struct ldap_x_ext_io_fns	iofns;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate     memset( &iofns, 0, sizeof(iofns));
107*7c478bd9Sstevel@tonic-gate     iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
108*7c478bd9Sstevel@tonic-gate     iofns.lextiof_read = prldap_read;
109*7c478bd9Sstevel@tonic-gate     iofns.lextiof_write = prldap_write;
110*7c478bd9Sstevel@tonic-gate     iofns.lextiof_poll = prldap_poll;
111*7c478bd9Sstevel@tonic-gate     iofns.lextiof_connect = prldap_connect;
112*7c478bd9Sstevel@tonic-gate     iofns.lextiof_close = prldap_close;
113*7c478bd9Sstevel@tonic-gate     if ( shared ) {
114*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_newhandle = prldap_shared_newhandle;
115*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_disposehandle = prldap_shared_disposehandle;
116*7c478bd9Sstevel@tonic-gate     } else {
117*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_newhandle = prldap_newhandle;
118*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_disposehandle = prldap_disposehandle;
119*7c478bd9Sstevel@tonic-gate     }
120*7c478bd9Sstevel@tonic-gate     if ( NULL != ld ) {
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * If we are dealing with a real ld, we allocate the session specific
123*7c478bd9Sstevel@tonic-gate 	 * data structure now.  If not allocated here, it will be allocated
124*7c478bd9Sstevel@tonic-gate 	 * inside prldap_newhandle() or prldap_shared_newhandle().
125*7c478bd9Sstevel@tonic-gate 	 */
126*7c478bd9Sstevel@tonic-gate 	if ( NULL ==
127*7c478bd9Sstevel@tonic-gate 		( iofns.lextiof_session_arg = prldap_session_arg_alloc())) {
128*7c478bd9Sstevel@tonic-gate 	    ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
129*7c478bd9Sstevel@tonic-gate 	    return( -1 );
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate     } else {
132*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_session_arg = NULL;
133*7c478bd9Sstevel@tonic-gate     }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) {
136*7c478bd9Sstevel@tonic-gate 	prldap_session_arg_free(
137*7c478bd9Sstevel@tonic-gate 		(PRLDAPIOSessionArg **) &iofns.lextiof_session_arg );
138*7c478bd9Sstevel@tonic-gate 	return( -1 );
139*7c478bd9Sstevel@tonic-gate     }
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate     return( 0 );
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate static PRIntervalTime
146*7c478bd9Sstevel@tonic-gate prldap_timeout2it( int ms_timeout, int ms_maxtimeout )
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate     PRIntervalTime	prit;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate     if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) {
151*7c478bd9Sstevel@tonic-gate 	prit = PR_INTERVAL_NO_WAIT;
152*7c478bd9Sstevel@tonic-gate     } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) {
153*7c478bd9Sstevel@tonic-gate 	prit = PR_INTERVAL_NO_TIMEOUT;
154*7c478bd9Sstevel@tonic-gate     } else {
155*7c478bd9Sstevel@tonic-gate 	prit = PR_MillisecondsToInterval( ms_timeout );
156*7c478bd9Sstevel@tonic-gate     }
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate     /* cap at maximum I/O timeout */
159*7c478bd9Sstevel@tonic-gate     if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) {
160*7c478bd9Sstevel@tonic-gate 	prit = LDAP_X_IO_TIMEOUT_NO_WAIT;
161*7c478bd9Sstevel@tonic-gate     } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) {
162*7c478bd9Sstevel@tonic-gate 	if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ||
163*7c478bd9Sstevel@tonic-gate 		    ms_timeout > ms_maxtimeout ) {
164*7c478bd9Sstevel@tonic-gate 	    prit = PR_MillisecondsToInterval( ms_maxtimeout );
165*7c478bd9Sstevel@tonic-gate 	}
166*7c478bd9Sstevel@tonic-gate     }
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
169*7c478bd9Sstevel@tonic-gate     if ( PR_INTERVAL_NO_WAIT == prit ) {
170*7c478bd9Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" );
171*7c478bd9Sstevel@tonic-gate     } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) {
172*7c478bd9Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" );
173*7c478bd9Sstevel@tonic-gate     } else {
174*7c478bd9Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: %dms\n",
175*7c478bd9Sstevel@tonic-gate 		PR_IntervalToMilliseconds(prit));
176*7c478bd9Sstevel@tonic-gate     }
177*7c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate     return( prit );
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
184*7c478bd9Sstevel@tonic-gate prldap_read( int s, void *buf, int bufsize,
185*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg )
186*7c478bd9Sstevel@tonic-gate {
187*7c478bd9Sstevel@tonic-gate     PRIntervalTime	prit;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate     prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT,
190*7c478bd9Sstevel@tonic-gate 			socketarg->prsock_io_max_timeout );
191*7c478bd9Sstevel@tonic-gate     return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit ));
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
196*7c478bd9Sstevel@tonic-gate prldap_write( int s, const void *buf, int len,
197*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg )
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate     PRIntervalTime	prit;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate     prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT,
202*7c478bd9Sstevel@tonic-gate 			socketarg->prsock_io_max_timeout );
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate     /*
205*7c478bd9Sstevel@tonic-gate      * Note the 4th parameter (flags) to PR_Send() has been obsoleted and
206*7c478bd9Sstevel@tonic-gate      * must always be 0
207*7c478bd9Sstevel@tonic-gate      */
208*7c478bd9Sstevel@tonic-gate     return( PR_Send( PRLDAP_GET_PRFD(socketarg), buf, len, 0, prit ));
209*7c478bd9Sstevel@tonic-gate }
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate struct prldap_eventmap_entry {
213*7c478bd9Sstevel@tonic-gate     PRInt16	evm_nspr;	/* corresponding NSPR PR_Poll() event */
214*7c478bd9Sstevel@tonic-gate     int		evm_ldap;	/* LDAP poll event */
215*7c478bd9Sstevel@tonic-gate };
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate static struct prldap_eventmap_entry prldap_eventmap[] = {
218*7c478bd9Sstevel@tonic-gate     { PR_POLL_READ,	LDAP_X_POLLIN },
219*7c478bd9Sstevel@tonic-gate     { PR_POLL_EXCEPT,	LDAP_X_POLLPRI },
220*7c478bd9Sstevel@tonic-gate     { PR_POLL_WRITE,	LDAP_X_POLLOUT },
221*7c478bd9Sstevel@tonic-gate     { PR_POLL_ERR,	LDAP_X_POLLERR },
222*7c478bd9Sstevel@tonic-gate     { PR_POLL_HUP,	LDAP_X_POLLHUP },
223*7c478bd9Sstevel@tonic-gate     { PR_POLL_NVAL,	LDAP_X_POLLNVAL },
224*7c478bd9Sstevel@tonic-gate };
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate #define PRLDAP_EVENTMAP_ENTRIES	\
227*7c478bd9Sstevel@tonic-gate 	sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry )
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
230*7c478bd9Sstevel@tonic-gate prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout,
231*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg )
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate     PRLDAPIOSessionArg	*prsessp = sessionarg;
234*7c478bd9Sstevel@tonic-gate     PRPollDesc		*pds;
235*7c478bd9Sstevel@tonic-gate     int			i, j, rc;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate     if ( NULL == prsessp ) {
238*7c478bd9Sstevel@tonic-gate 	prldap_set_system_errno( EINVAL );
239*7c478bd9Sstevel@tonic-gate 	return( -1 );
240*7c478bd9Sstevel@tonic-gate     }
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate     /* allocate or resize NSPR poll descriptor array */
243*7c478bd9Sstevel@tonic-gate     if ( prsessp->prsess_pollds_count < nfds ) {
244*7c478bd9Sstevel@tonic-gate 	pds = prldap_safe_realloc( prsessp->prsess_pollds,
245*7c478bd9Sstevel@tonic-gate 		( nfds + PRLDAP_POLL_ARRAY_GROWTH )
246*7c478bd9Sstevel@tonic-gate 		* sizeof( PRPollDesc ));
247*7c478bd9Sstevel@tonic-gate 	if ( NULL == pds ) {
248*7c478bd9Sstevel@tonic-gate 	    prldap_set_system_errno( prldap_prerr2errno());
249*7c478bd9Sstevel@tonic-gate 	    return( -1 );
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate 	prsessp->prsess_pollds = pds;
252*7c478bd9Sstevel@tonic-gate 	prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH;
253*7c478bd9Sstevel@tonic-gate     } else {
254*7c478bd9Sstevel@tonic-gate 	pds = prsessp->prsess_pollds;
255*7c478bd9Sstevel@tonic-gate     }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate     /* populate NSPR poll info. based on LDAP info. */
258*7c478bd9Sstevel@tonic-gate     for ( i = 0; i < nfds; ++i ) {
259*7c478bd9Sstevel@tonic-gate 	if ( NULL == fds[i].lpoll_socketarg ) {
260*7c478bd9Sstevel@tonic-gate 	    pds[i].fd = NULL;
261*7c478bd9Sstevel@tonic-gate 	} else {
262*7c478bd9Sstevel@tonic-gate 	    pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg );
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 	pds[i].in_flags = pds[i].out_flags = 0;
265*7c478bd9Sstevel@tonic-gate 	if ( fds[i].lpoll_fd >= 0 ) {
266*7c478bd9Sstevel@tonic-gate 	    for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) {
267*7c478bd9Sstevel@tonic-gate 		if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap )
268*7c478bd9Sstevel@tonic-gate 		    != 0 ) {
269*7c478bd9Sstevel@tonic-gate 			pds[i].in_flags |= prldap_eventmap[j].evm_nspr;
270*7c478bd9Sstevel@tonic-gate 		}
271*7c478bd9Sstevel@tonic-gate 	    }
272*7c478bd9Sstevel@tonic-gate 	}
273*7c478bd9Sstevel@tonic-gate 	fds[i].lpoll_revents = 0;	/* clear revents */
274*7c478bd9Sstevel@tonic-gate     }
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate     /* call PR_Poll() to do the real work */
277*7c478bd9Sstevel@tonic-gate     rc = PR_Poll( pds, nfds,
278*7c478bd9Sstevel@tonic-gate 	    prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout ));
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate     /* populate LDAP info. based on NSPR results */
281*7c478bd9Sstevel@tonic-gate     for ( i = 0; i < nfds; ++i ) {
282*7c478bd9Sstevel@tonic-gate 	if ( pds[i].fd != NULL ) {
283*7c478bd9Sstevel@tonic-gate 	    for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) {
284*7c478bd9Sstevel@tonic-gate 		if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr )
285*7c478bd9Sstevel@tonic-gate 			!= 0 ) {
286*7c478bd9Sstevel@tonic-gate 		    fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap;
287*7c478bd9Sstevel@tonic-gate 		}
288*7c478bd9Sstevel@tonic-gate 	    }
289*7c478bd9Sstevel@tonic-gate 	}
290*7c478bd9Sstevel@tonic-gate     }
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate     return( rc );
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate /*
297*7c478bd9Sstevel@tonic-gate  * Utility function to try one TCP connect()
298*7c478bd9Sstevel@tonic-gate  * Returns 1 if successful and -1 if not.  Sets the NSPR fd inside prsockp.
299*7c478bd9Sstevel@tonic-gate  */
300*7c478bd9Sstevel@tonic-gate static int
301*7c478bd9Sstevel@tonic-gate prldap_try_one_address( struct lextiof_socket_private *prsockp,
302*7c478bd9Sstevel@tonic-gate     PRNetAddr *addrp, int port, int timeout, unsigned long options )
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate     /*
305*7c478bd9Sstevel@tonic-gate      * Set up address and open a TCP socket:
306*7c478bd9Sstevel@tonic-gate      */
307*7c478bd9Sstevel@tonic-gate     if ( PR_SUCCESS != PR_SetNetAddr( PR_IpAddrNull, /* don't touch IP addr. */
308*7c478bd9Sstevel@tonic-gate 		PRLDAP_DEFAULT_ADDRESS_FAMILY, (PRUint16)port, addrp )) {
309*7c478bd9Sstevel@tonic-gate 	return( -1 );
310*7c478bd9Sstevel@tonic-gate     }
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate     if (( prsockp->prsock_prfd = PR_OpenTCPSocket(
313*7c478bd9Sstevel@tonic-gate 		PRLDAP_DEFAULT_ADDRESS_FAMILY )) == NULL ) {
314*7c478bd9Sstevel@tonic-gate 	return( -1 );
315*7c478bd9Sstevel@tonic-gate     }
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate     /*
318*7c478bd9Sstevel@tonic-gate      * Set nonblocking option if requested:
319*7c478bd9Sstevel@tonic-gate      */
320*7c478bd9Sstevel@tonic-gate     if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) {
321*7c478bd9Sstevel@tonic-gate 	PRSocketOptionData	optdata;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	optdata.option = PR_SockOpt_Nonblocking;
324*7c478bd9Sstevel@tonic-gate 	optdata.value.non_blocking = PR_TRUE;
325*7c478bd9Sstevel@tonic-gate 	if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata )
326*7c478bd9Sstevel@tonic-gate 		    != PR_SUCCESS ) {
327*7c478bd9Sstevel@tonic-gate 	    prldap_set_system_errno( prldap_prerr2errno());
328*7c478bd9Sstevel@tonic-gate 	    PR_Close( prsockp->prsock_prfd );
329*7c478bd9Sstevel@tonic-gate 	    return( -1 );
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate     }
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
334*7c478bd9Sstevel@tonic-gate     {
335*7c478bd9Sstevel@tonic-gate 	char	buf[ 256 ], *p, *fmtstr;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) {
338*7c478bd9Sstevel@tonic-gate 		strcpy( buf, "conversion failed!" );
339*7c478bd9Sstevel@tonic-gate 	}
340*7c478bd9Sstevel@tonic-gate 	if ( strncmp( buf, "::ffff:", 7 ) == 0 ) {
341*7c478bd9Sstevel@tonic-gate 		/* IPv4 address mapped into IPv6 address space */
342*7c478bd9Sstevel@tonic-gate 		p = buf + 7;
343*7c478bd9Sstevel@tonic-gate 		fmtstr = "prldap_try_one_address(): Trying %s:%d...\n";
344*7c478bd9Sstevel@tonic-gate 	} else {
345*7c478bd9Sstevel@tonic-gate 		p = buf;
346*7c478bd9Sstevel@tonic-gate 		fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n";
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate 	fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port ));
349*7c478bd9Sstevel@tonic-gate     }
350*7c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate     /*
353*7c478bd9Sstevel@tonic-gate      * Try to open the TCP connection itself:
354*7c478bd9Sstevel@tonic-gate      */
355*7c478bd9Sstevel@tonic-gate     if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp,
356*7c478bd9Sstevel@tonic-gate 		prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout ))) {
357*7c478bd9Sstevel@tonic-gate 	PR_Close( prsockp->prsock_prfd );
358*7c478bd9Sstevel@tonic-gate 	prsockp->prsock_prfd = NULL;
359*7c478bd9Sstevel@tonic-gate 	return( -1 );
360*7c478bd9Sstevel@tonic-gate     }
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
363*7c478bd9Sstevel@tonic-gate     fputs( "prldap_try_one_address(): Connected.\n", stderr );
364*7c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate     /*
367*7c478bd9Sstevel@tonic-gate      * Success.  Return a valid file descriptor (1 is always valid)
368*7c478bd9Sstevel@tonic-gate      */
369*7c478bd9Sstevel@tonic-gate     return( 1 );
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate /*
374*7c478bd9Sstevel@tonic-gate  * XXXmcs: At present, this code ignores the timeout when doing DNS lookups.
375*7c478bd9Sstevel@tonic-gate  */
376*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
377*7c478bd9Sstevel@tonic-gate prldap_connect( const char *hostlist, int defport, int timeout,
378*7c478bd9Sstevel@tonic-gate 	unsigned long options, struct lextiof_session_private *sessionarg,
379*7c478bd9Sstevel@tonic-gate 	struct lextiof_socket_private **socketargp
380*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
381*7c478bd9Sstevel@tonic-gate 	, void **dhost )
382*7c478bd9Sstevel@tonic-gate #else
383*7c478bd9Sstevel@tonic-gate 	)
384*7c478bd9Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
385*7c478bd9Sstevel@tonic-gate {
386*7c478bd9Sstevel@tonic-gate     int					rc, parse_err, port;
387*7c478bd9Sstevel@tonic-gate     char				*host, hbuf[ PR_NETDB_BUF_SIZE ];
388*7c478bd9Sstevel@tonic-gate     struct ldap_x_hostlist_status	*status;
389*7c478bd9Sstevel@tonic-gate     struct lextiof_socket_private	*prsockp;
390*7c478bd9Sstevel@tonic-gate     PRNetAddr				addr;
391*7c478bd9Sstevel@tonic-gate     PRHostEnt				hent;
392*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
393*7c478bd9Sstevel@tonic-gate     char				*hostname = NULL;
394*7c478bd9Sstevel@tonic-gate     char				*nsldapi_strdup(char *);
395*7c478bd9Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate     if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
398*7c478bd9Sstevel@tonic-gate 	prldap_set_system_errno( EINVAL );
399*7c478bd9Sstevel@tonic-gate 	return( -1 );
400*7c478bd9Sstevel@tonic-gate     }
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate     if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) {
403*7c478bd9Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
404*7c478bd9Sstevel@tonic-gate 	return( -1 );
405*7c478bd9Sstevel@tonic-gate     }
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate     rc = -1;	/* pessimistic */
408*7c478bd9Sstevel@tonic-gate     for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port,
409*7c478bd9Sstevel@tonic-gate 		&status );
410*7c478bd9Sstevel@tonic-gate 		rc < 0 && LDAP_SUCCESS == parse_err && NULL != host;
411*7c478bd9Sstevel@tonic-gate 		parse_err = ldap_x_hostlist_next( &host, &port, status )) {
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) {
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 		if ( PRLDAP_DEFAULT_ADDRESS_FAMILY == PR_AF_INET6 &&
416*7c478bd9Sstevel@tonic-gate 				PR_AF_INET == PR_NetAddrFamily( &addr )) {
417*7c478bd9Sstevel@tonic-gate 			PRUint32	ipv4ip = addr.inet.ip;
418*7c478bd9Sstevel@tonic-gate 			memset( &addr, 0, sizeof(addr));
419*7c478bd9Sstevel@tonic-gate 			PR_ConvertIPv4AddrToIPv6( ipv4ip, &addr.ipv6.ip );
420*7c478bd9Sstevel@tonic-gate 			addr.ipv6.family = PR_AF_INET6;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 		}
423*7c478bd9Sstevel@tonic-gate 	    rc = prldap_try_one_address( prsockp, &addr, port,
424*7c478bd9Sstevel@tonic-gate 			timeout, options );
425*7c478bd9Sstevel@tonic-gate 	} else {
426*7c478bd9Sstevel@tonic-gate 	    if ( PR_SUCCESS == PR_GetIPNodeByName( host,
427*7c478bd9Sstevel@tonic-gate 			PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT | PR_AI_ALL, hbuf,
428*7c478bd9Sstevel@tonic-gate 			sizeof( hbuf ), &hent )) {
429*7c478bd9Sstevel@tonic-gate 		PRIntn enumIndex = 0;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 		while ( rc < 0 && ( enumIndex = PR_EnumerateHostEnt(
432*7c478bd9Sstevel@tonic-gate 			    enumIndex, &hent, (PRUint16)port, &addr )) > 0 ) {
433*7c478bd9Sstevel@tonic-gate 		    rc = prldap_try_one_address( prsockp, &addr, port,
434*7c478bd9Sstevel@tonic-gate 				timeout, options );
435*7c478bd9Sstevel@tonic-gate 		}
436*7c478bd9Sstevel@tonic-gate 	    }
437*7c478bd9Sstevel@tonic-gate 	}
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
440*7c478bd9Sstevel@tonic-gate 	if ( NULL != hostname ) ldap_memfree(hostname);
441*7c478bd9Sstevel@tonic-gate 	hostname = nsldapi_strdup(host);
442*7c478bd9Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
443*7c478bd9Sstevel@tonic-gate 	ldap_memfree( host );
444*7c478bd9Sstevel@tonic-gate     }
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate     ldap_x_hostlist_statusfree( status );
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate     if ( rc < 0 ) {
449*7c478bd9Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
450*7c478bd9Sstevel@tonic-gate 	prldap_socket_arg_free( &prsockp );
451*7c478bd9Sstevel@tonic-gate     } else {
452*7c478bd9Sstevel@tonic-gate 	*socketargp = prsockp;
453*7c478bd9Sstevel@tonic-gate     }
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK
456*7c478bd9Sstevel@tonic-gate     if ( NULL != hostname && NULL != dhost ) *dhost = hostname;
457*7c478bd9Sstevel@tonic-gate     else if ( NULL != hostname ) ldap_memfree(hostname);
458*7c478bd9Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate     return( rc );
461*7c478bd9Sstevel@tonic-gate }
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
465*7c478bd9Sstevel@tonic-gate prldap_close( int s, struct lextiof_socket_private *socketarg )
466*7c478bd9Sstevel@tonic-gate {
467*7c478bd9Sstevel@tonic-gate     int		rc;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate     rc = 0;
470*7c478bd9Sstevel@tonic-gate     if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) {
471*7c478bd9Sstevel@tonic-gate 	rc = -1;
472*7c478bd9Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
473*7c478bd9Sstevel@tonic-gate     }
474*7c478bd9Sstevel@tonic-gate     prldap_socket_arg_free( &socketarg );
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate     return( rc );
477*7c478bd9Sstevel@tonic-gate }
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate /*
481*7c478bd9Sstevel@tonic-gate  * LDAP session handle creation callback.
482*7c478bd9Sstevel@tonic-gate  *
483*7c478bd9Sstevel@tonic-gate  * Allocate a session argument if not already done, and then call the
484*7c478bd9Sstevel@tonic-gate  * thread's new handle function.
485*7c478bd9Sstevel@tonic-gate  */
486*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
487*7c478bd9Sstevel@tonic-gate prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg )
488*7c478bd9Sstevel@tonic-gate {
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate     if ( NULL == sessionarg ) {
491*7c478bd9Sstevel@tonic-gate 	struct ldap_x_ext_io_fns	iofns;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	memset( &iofns, 0, sizeof(iofns));
494*7c478bd9Sstevel@tonic-gate 	iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
495*7c478bd9Sstevel@tonic-gate 	if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
496*7c478bd9Sstevel@tonic-gate 		(void *)&iofns ) < 0 ) {
497*7c478bd9Sstevel@tonic-gate 	    return( ldap_get_lderrno( ld, NULL, NULL ));
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 	if ( NULL ==
500*7c478bd9Sstevel@tonic-gate 		( iofns.lextiof_session_arg = prldap_session_arg_alloc())) {
501*7c478bd9Sstevel@tonic-gate 	    return( LDAP_NO_MEMORY );
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 	if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
504*7c478bd9Sstevel@tonic-gate 		    (void *)&iofns ) < 0 ) {
505*7c478bd9Sstevel@tonic-gate 	    return( ldap_get_lderrno( ld, NULL, NULL ));
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate     }
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate     return( LDAP_SUCCESS );
510*7c478bd9Sstevel@tonic-gate }
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate /* only called/installed if shared is non-zero. */
514*7c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK
515*7c478bd9Sstevel@tonic-gate prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg )
516*7c478bd9Sstevel@tonic-gate {
517*7c478bd9Sstevel@tonic-gate     int		rc;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate     if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) {
520*7c478bd9Sstevel@tonic-gate 	rc = prldap_thread_new_handle( ld, sessionarg );
521*7c478bd9Sstevel@tonic-gate     }
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate     return( rc );
524*7c478bd9Sstevel@tonic-gate }
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK
528*7c478bd9Sstevel@tonic-gate prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg )
529*7c478bd9Sstevel@tonic-gate {
530*7c478bd9Sstevel@tonic-gate     prldap_session_arg_free( &sessionarg );
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate /* only called/installed if shared is non-zero */
535*7c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK
536*7c478bd9Sstevel@tonic-gate prldap_shared_disposehandle( LDAP *ld,
537*7c478bd9Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg )
538*7c478bd9Sstevel@tonic-gate {
539*7c478bd9Sstevel@tonic-gate     prldap_thread_dispose_handle( ld, sessionarg );
540*7c478bd9Sstevel@tonic-gate     prldap_disposehandle( ld, sessionarg );
541*7c478bd9Sstevel@tonic-gate }
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate /*
545*7c478bd9Sstevel@tonic-gate  * Allocate a session argument.
546*7c478bd9Sstevel@tonic-gate  */
547*7c478bd9Sstevel@tonic-gate static PRLDAPIOSessionArg *
548*7c478bd9Sstevel@tonic-gate prldap_session_arg_alloc( void )
549*7c478bd9Sstevel@tonic-gate {
550*7c478bd9Sstevel@tonic-gate     PRLDAPIOSessionArg		*prsessp;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate     prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg ));
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate     if ( NULL != prsessp ) {
555*7c478bd9Sstevel@tonic-gate 	/* copy global defaults to the new session handle */
556*7c478bd9Sstevel@tonic-gate 	prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout;
557*7c478bd9Sstevel@tonic-gate     }
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate     return( prsessp );
560*7c478bd9Sstevel@tonic-gate }
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate static void
564*7c478bd9Sstevel@tonic-gate prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp )
565*7c478bd9Sstevel@tonic-gate {
566*7c478bd9Sstevel@tonic-gate     if ( NULL != prsesspp && NULL != *prsesspp ) {
567*7c478bd9Sstevel@tonic-gate 	if ( NULL != (*prsesspp)->prsess_pollds ) {
568*7c478bd9Sstevel@tonic-gate 	    PR_Free( (*prsesspp)->prsess_pollds );
569*7c478bd9Sstevel@tonic-gate 	    (*prsesspp)->prsess_pollds = NULL;
570*7c478bd9Sstevel@tonic-gate 	}
571*7c478bd9Sstevel@tonic-gate 	PR_Free( *prsesspp );
572*7c478bd9Sstevel@tonic-gate 	*prsesspp = NULL;
573*7c478bd9Sstevel@tonic-gate     }
574*7c478bd9Sstevel@tonic-gate }
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate /*
578*7c478bd9Sstevel@tonic-gate  * Given an LDAP session handle, retrieve a session argument.
579*7c478bd9Sstevel@tonic-gate  * Returns an LDAP error code.
580*7c478bd9Sstevel@tonic-gate  */
581*7c478bd9Sstevel@tonic-gate int
582*7c478bd9Sstevel@tonic-gate prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp )
583*7c478bd9Sstevel@tonic-gate {
584*7c478bd9Sstevel@tonic-gate     struct ldap_x_ext_io_fns	iofns;
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate     if ( NULL == ld || NULL == sessargpp ) {
587*7c478bd9Sstevel@tonic-gate 	/* XXXmcs: NULL ld's are not supported */
588*7c478bd9Sstevel@tonic-gate 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
589*7c478bd9Sstevel@tonic-gate 	return( LDAP_PARAM_ERROR );
590*7c478bd9Sstevel@tonic-gate     }
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate     memset( &iofns, 0, sizeof(iofns));
593*7c478bd9Sstevel@tonic-gate     iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
594*7c478bd9Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
595*7c478bd9Sstevel@tonic-gate 	return( ldap_get_lderrno( ld, NULL, NULL ));
596*7c478bd9Sstevel@tonic-gate     }
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate     if ( NULL == iofns.lextiof_session_arg ) {
599*7c478bd9Sstevel@tonic-gate 	ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
600*7c478bd9Sstevel@tonic-gate 	return( LDAP_LOCAL_ERROR );
601*7c478bd9Sstevel@tonic-gate     }
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate     *sessargpp = iofns.lextiof_session_arg;
604*7c478bd9Sstevel@tonic-gate     return( LDAP_SUCCESS );
605*7c478bd9Sstevel@tonic-gate }
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate /*
609*7c478bd9Sstevel@tonic-gate  * Given an LDAP session handle, retrieve a socket argument.
610*7c478bd9Sstevel@tonic-gate  * Returns an LDAP error code.
611*7c478bd9Sstevel@tonic-gate  */
612*7c478bd9Sstevel@tonic-gate int
613*7c478bd9Sstevel@tonic-gate prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp )
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate     Sockbuf *sbp;
616*7c478bd9Sstevel@tonic-gate     struct lber_x_ext_io_fns    extiofns;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate     if ( NULL == ld || NULL == sockargpp ) {
619*7c478bd9Sstevel@tonic-gate         /* XXXmcs: NULL ld's are not supported */
620*7c478bd9Sstevel@tonic-gate         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
621*7c478bd9Sstevel@tonic-gate         return( LDAP_PARAM_ERROR );
622*7c478bd9Sstevel@tonic-gate     }
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) {
625*7c478bd9Sstevel@tonic-gate         return( ldap_get_lderrno( ld, NULL, NULL ));
626*7c478bd9Sstevel@tonic-gate     }
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate     memset( &extiofns, 0, sizeof(extiofns));
629*7c478bd9Sstevel@tonic-gate     extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
630*7c478bd9Sstevel@tonic-gate     if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS,
631*7c478bd9Sstevel@tonic-gate         (void *)&extiofns ) < 0 ) {
632*7c478bd9Sstevel@tonic-gate         return( ldap_get_lderrno( ld, NULL, NULL ));
633*7c478bd9Sstevel@tonic-gate     }
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate     if ( NULL == extiofns.lbextiofn_socket_arg ) {
636*7c478bd9Sstevel@tonic-gate         ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
637*7c478bd9Sstevel@tonic-gate         return( LDAP_LOCAL_ERROR );
638*7c478bd9Sstevel@tonic-gate     }
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate     *sockargpp = extiofns.lbextiofn_socket_arg;
641*7c478bd9Sstevel@tonic-gate     return( LDAP_SUCCESS );
642*7c478bd9Sstevel@tonic-gate }
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate /*
646*7c478bd9Sstevel@tonic-gate  * Allocate a socket argument.
647*7c478bd9Sstevel@tonic-gate  */
648*7c478bd9Sstevel@tonic-gate static PRLDAPIOSocketArg *
649*7c478bd9Sstevel@tonic-gate prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg )
650*7c478bd9Sstevel@tonic-gate {
651*7c478bd9Sstevel@tonic-gate     PRLDAPIOSocketArg		*prsockp;
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate     prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg ));
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate     if ( NULL != prsockp && NULL != sessionarg ) {
656*7c478bd9Sstevel@tonic-gate 	/* copy socket defaults from the session */
657*7c478bd9Sstevel@tonic-gate 	prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout;
658*7c478bd9Sstevel@tonic-gate     }
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate     return( prsockp );
661*7c478bd9Sstevel@tonic-gate }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate static void
665*7c478bd9Sstevel@tonic-gate prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp )
666*7c478bd9Sstevel@tonic-gate {
667*7c478bd9Sstevel@tonic-gate     if ( NULL != prsockpp && NULL != *prsockpp ) {
668*7c478bd9Sstevel@tonic-gate 	PR_Free( *prsockpp );
669*7c478bd9Sstevel@tonic-gate 	*prsockpp = NULL;
670*7c478bd9Sstevel@tonic-gate     }
671*7c478bd9Sstevel@tonic-gate }
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate static void *
675*7c478bd9Sstevel@tonic-gate prldap_safe_realloc( void *ptr, PRUint32 size )
676*7c478bd9Sstevel@tonic-gate {
677*7c478bd9Sstevel@tonic-gate     void	*p;
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate     if ( NULL == ptr ) {
680*7c478bd9Sstevel@tonic-gate 	p = PR_Malloc( size );
681*7c478bd9Sstevel@tonic-gate     } else {
682*7c478bd9Sstevel@tonic-gate 	p = PR_Realloc( ptr, size );
683*7c478bd9Sstevel@tonic-gate     }
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate     return( p );
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /* returns an LDAP result code */
691*7c478bd9Sstevel@tonic-gate int
692*7c478bd9Sstevel@tonic-gate prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout )
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate     int	rc = LDAP_SUCCESS;	/* optimistic */
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate     if ( NULL == prsessp ) {
697*7c478bd9Sstevel@tonic-gate 	prldap_default_io_max_timeout = io_max_timeout;
698*7c478bd9Sstevel@tonic-gate     } else {
699*7c478bd9Sstevel@tonic-gate 	prsessp->prsess_io_max_timeout = io_max_timeout;
700*7c478bd9Sstevel@tonic-gate     }
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate     return( rc );
703*7c478bd9Sstevel@tonic-gate }
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate /* returns an LDAP result code */
707*7c478bd9Sstevel@tonic-gate int
708*7c478bd9Sstevel@tonic-gate prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp )
709*7c478bd9Sstevel@tonic-gate {
710*7c478bd9Sstevel@tonic-gate     int	rc = LDAP_SUCCESS;	/* optimistic */
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate     if ( NULL == io_max_timeoutp ) {
713*7c478bd9Sstevel@tonic-gate 	rc = LDAP_PARAM_ERROR;
714*7c478bd9Sstevel@tonic-gate     } else if ( NULL == prsessp ) {
715*7c478bd9Sstevel@tonic-gate 	*io_max_timeoutp = prldap_default_io_max_timeout;
716*7c478bd9Sstevel@tonic-gate     } else {
717*7c478bd9Sstevel@tonic-gate 	*io_max_timeoutp = prsessp->prsess_io_max_timeout;
718*7c478bd9Sstevel@tonic-gate     }
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate     return( rc );
721*7c478bd9Sstevel@tonic-gate }
722