xref: /onnv-gate/usr/src/lib/libldap5/sources/ldap/prldap/ldappr-io.c (revision 10284:f12571ecd37e)
10Sstevel@tonic-gate /*
2*10284SMilan.Jurik@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
80Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
90Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
100Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
130Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
140Sstevel@tonic-gate  * implied. See the License for the specific language governing
150Sstevel@tonic-gate  * rights and limitations under the License.
160Sstevel@tonic-gate  *
170Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
180Sstevel@tonic-gate  * March 31, 1998.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
210Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
220Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
230Sstevel@tonic-gate  * Rights Reserved.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * Contributor(s):
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Extended I/O callback functions for libldap that use
300Sstevel@tonic-gate  * NSPR (Netscape Portable Runtime) I/O.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * High level strategy: we use the socket-specific arg to hold our own data
330Sstevel@tonic-gate  * structure that includes the NSPR file handle (PRFileDesc *), among other
340Sstevel@tonic-gate  * useful information.  We use the default argument to hold an LDAP session
350Sstevel@tonic-gate  * handle specific data structure.
360Sstevel@tonic-gate  */
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include "ldappr-int.h"
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define PRLDAP_POLL_ARRAY_GROWTH  5  /* grow arrays 5 elements at a time */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  * Local function prototypes:
450Sstevel@tonic-gate  */
460Sstevel@tonic-gate static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout );
470Sstevel@tonic-gate static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize,
480Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
490Sstevel@tonic-gate static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len,
500Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
510Sstevel@tonic-gate static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds,
520Sstevel@tonic-gate 	int timeout, struct lextiof_session_private *sessionarg );
530Sstevel@tonic-gate static int LDAP_CALLBACK prldap_connect( const char *hostlist, int defport,
540Sstevel@tonic-gate 	int timeout, unsigned long options,
550Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg,
560Sstevel@tonic-gate 	struct lextiof_socket_private **socketargp
570Sstevel@tonic-gate #ifdef _SOLARIS_SDK
580Sstevel@tonic-gate 	, void **dhost );
590Sstevel@tonic-gate #else
600Sstevel@tonic-gate 	);
610Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
620Sstevel@tonic-gate static int LDAP_CALLBACK prldap_close( int s,
630Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg );
640Sstevel@tonic-gate static int LDAP_CALLBACK prldap_newhandle( LDAP *ld,
650Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
660Sstevel@tonic-gate static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld,
670Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
680Sstevel@tonic-gate static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld,
690Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
700Sstevel@tonic-gate static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld,
710Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg );
720Sstevel@tonic-gate static PRLDAPIOSessionArg *prldap_session_arg_alloc( void );
730Sstevel@tonic-gate static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp );
740Sstevel@tonic-gate static PRLDAPIOSocketArg *prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg );
750Sstevel@tonic-gate static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp );
760Sstevel@tonic-gate static void *prldap_safe_realloc( void *ptr, PRUint32 size );
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate  * Local macros:
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate /* given a socket-specific arg, return the corresponding PRFileDesc * */
840Sstevel@tonic-gate #define PRLDAP_GET_PRFD( socketarg )	\
850Sstevel@tonic-gate 		(((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd)
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Static variables.
890Sstevel@tonic-gate  */
900Sstevel@tonic-gate static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate  * Install NSPR I/O functions into ld (if ld is NULL, they are installed
940Sstevel@tonic-gate  * as the default functions for new LDAP * handles).
950Sstevel@tonic-gate  *
960Sstevel@tonic-gate  * Returns 0 if all goes well and -1 if not.
970Sstevel@tonic-gate  */
980Sstevel@tonic-gate int
prldap_install_io_functions(LDAP * ld,int shared)990Sstevel@tonic-gate prldap_install_io_functions( LDAP *ld, int shared )
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate     struct ldap_x_ext_io_fns	iofns;
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate     memset( &iofns, 0, sizeof(iofns));
1040Sstevel@tonic-gate     iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
1050Sstevel@tonic-gate     iofns.lextiof_read = prldap_read;
1060Sstevel@tonic-gate     iofns.lextiof_write = prldap_write;
1070Sstevel@tonic-gate     iofns.lextiof_poll = prldap_poll;
1080Sstevel@tonic-gate     iofns.lextiof_connect = prldap_connect;
1090Sstevel@tonic-gate     iofns.lextiof_close = prldap_close;
1100Sstevel@tonic-gate     if ( shared ) {
1110Sstevel@tonic-gate 	iofns.lextiof_newhandle = prldap_shared_newhandle;
1120Sstevel@tonic-gate 	iofns.lextiof_disposehandle = prldap_shared_disposehandle;
1130Sstevel@tonic-gate     } else {
1140Sstevel@tonic-gate 	iofns.lextiof_newhandle = prldap_newhandle;
1150Sstevel@tonic-gate 	iofns.lextiof_disposehandle = prldap_disposehandle;
1160Sstevel@tonic-gate     }
1170Sstevel@tonic-gate     if ( NULL != ld ) {
1180Sstevel@tonic-gate 	/*
1190Sstevel@tonic-gate 	 * If we are dealing with a real ld, we allocate the session specific
1200Sstevel@tonic-gate 	 * data structure now.  If not allocated here, it will be allocated
1210Sstevel@tonic-gate 	 * inside prldap_newhandle() or prldap_shared_newhandle().
1220Sstevel@tonic-gate 	 */
1230Sstevel@tonic-gate 	if ( NULL ==
1240Sstevel@tonic-gate 		( iofns.lextiof_session_arg = prldap_session_arg_alloc())) {
1250Sstevel@tonic-gate 	    ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
1260Sstevel@tonic-gate 	    return( -1 );
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate     } else {
1290Sstevel@tonic-gate 	iofns.lextiof_session_arg = NULL;
1300Sstevel@tonic-gate     }
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) {
1330Sstevel@tonic-gate 	prldap_session_arg_free(
1340Sstevel@tonic-gate 		(PRLDAPIOSessionArg **) &iofns.lextiof_session_arg );
1350Sstevel@tonic-gate 	return( -1 );
1360Sstevel@tonic-gate     }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate     return( 0 );
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate static PRIntervalTime
prldap_timeout2it(int ms_timeout,int ms_maxtimeout)1430Sstevel@tonic-gate prldap_timeout2it( int ms_timeout, int ms_maxtimeout )
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate     PRIntervalTime	prit;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate     if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) {
1480Sstevel@tonic-gate 	prit = PR_INTERVAL_NO_WAIT;
1490Sstevel@tonic-gate     } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) {
1500Sstevel@tonic-gate 	prit = PR_INTERVAL_NO_TIMEOUT;
1510Sstevel@tonic-gate     } else {
1520Sstevel@tonic-gate 	prit = PR_MillisecondsToInterval( ms_timeout );
1530Sstevel@tonic-gate     }
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate     /* cap at maximum I/O timeout */
1560Sstevel@tonic-gate     if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) {
1570Sstevel@tonic-gate 	prit = LDAP_X_IO_TIMEOUT_NO_WAIT;
1580Sstevel@tonic-gate     } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) {
1590Sstevel@tonic-gate 	if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ||
1600Sstevel@tonic-gate 		    ms_timeout > ms_maxtimeout ) {
1610Sstevel@tonic-gate 	    prit = PR_MillisecondsToInterval( ms_maxtimeout );
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate     }
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
1660Sstevel@tonic-gate     if ( PR_INTERVAL_NO_WAIT == prit ) {
1670Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" );
1680Sstevel@tonic-gate     } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) {
1690Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" );
1700Sstevel@tonic-gate     } else {
1710Sstevel@tonic-gate 	fprintf( stderr, "prldap_timeout2it: %dms\n",
1720Sstevel@tonic-gate 		PR_IntervalToMilliseconds(prit));
1730Sstevel@tonic-gate     }
1740Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate     return( prit );
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_read(int s,void * buf,int bufsize,struct lextiof_socket_private * socketarg)1810Sstevel@tonic-gate prldap_read( int s, void *buf, int bufsize,
1820Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg )
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate     PRIntervalTime	prit;
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate     prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT,
1870Sstevel@tonic-gate 			socketarg->prsock_io_max_timeout );
1880Sstevel@tonic-gate     return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit ));
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_write(int s,const void * buf,int len,struct lextiof_socket_private * socketarg)1930Sstevel@tonic-gate prldap_write( int s, const void *buf, int len,
1940Sstevel@tonic-gate 	struct lextiof_socket_private *socketarg )
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate     PRIntervalTime	prit;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate     prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT,
1990Sstevel@tonic-gate 			socketarg->prsock_io_max_timeout );
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate     /*
2020Sstevel@tonic-gate      * Note the 4th parameter (flags) to PR_Send() has been obsoleted and
2030Sstevel@tonic-gate      * must always be 0
2040Sstevel@tonic-gate      */
2050Sstevel@tonic-gate     return( PR_Send( PRLDAP_GET_PRFD(socketarg), buf, len, 0, prit ));
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate struct prldap_eventmap_entry {
2100Sstevel@tonic-gate     PRInt16	evm_nspr;	/* corresponding NSPR PR_Poll() event */
2110Sstevel@tonic-gate     int		evm_ldap;	/* LDAP poll event */
2120Sstevel@tonic-gate };
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate static struct prldap_eventmap_entry prldap_eventmap[] = {
2150Sstevel@tonic-gate     { PR_POLL_READ,	LDAP_X_POLLIN },
2160Sstevel@tonic-gate     { PR_POLL_EXCEPT,	LDAP_X_POLLPRI },
2170Sstevel@tonic-gate     { PR_POLL_WRITE,	LDAP_X_POLLOUT },
2180Sstevel@tonic-gate     { PR_POLL_ERR,	LDAP_X_POLLERR },
2190Sstevel@tonic-gate     { PR_POLL_HUP,	LDAP_X_POLLHUP },
2200Sstevel@tonic-gate     { PR_POLL_NVAL,	LDAP_X_POLLNVAL },
2210Sstevel@tonic-gate };
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate #define PRLDAP_EVENTMAP_ENTRIES	\
2240Sstevel@tonic-gate 	sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry )
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_poll(LDAP_X_PollFD fds[],int nfds,int timeout,struct lextiof_session_private * sessionarg)2270Sstevel@tonic-gate prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout,
2280Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg )
2290Sstevel@tonic-gate {
2300Sstevel@tonic-gate     PRLDAPIOSessionArg	*prsessp = sessionarg;
2310Sstevel@tonic-gate     PRPollDesc		*pds;
2320Sstevel@tonic-gate     int			i, j, rc;
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate     if ( NULL == prsessp ) {
2350Sstevel@tonic-gate 	prldap_set_system_errno( EINVAL );
2360Sstevel@tonic-gate 	return( -1 );
2370Sstevel@tonic-gate     }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate     /* allocate or resize NSPR poll descriptor array */
2400Sstevel@tonic-gate     if ( prsessp->prsess_pollds_count < nfds ) {
2410Sstevel@tonic-gate 	pds = prldap_safe_realloc( prsessp->prsess_pollds,
2420Sstevel@tonic-gate 		( nfds + PRLDAP_POLL_ARRAY_GROWTH )
2430Sstevel@tonic-gate 		* sizeof( PRPollDesc ));
2440Sstevel@tonic-gate 	if ( NULL == pds ) {
2450Sstevel@tonic-gate 	    prldap_set_system_errno( prldap_prerr2errno());
2460Sstevel@tonic-gate 	    return( -1 );
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	prsessp->prsess_pollds = pds;
2490Sstevel@tonic-gate 	prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH;
2500Sstevel@tonic-gate     } else {
2510Sstevel@tonic-gate 	pds = prsessp->prsess_pollds;
2520Sstevel@tonic-gate     }
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate     /* populate NSPR poll info. based on LDAP info. */
2550Sstevel@tonic-gate     for ( i = 0; i < nfds; ++i ) {
2560Sstevel@tonic-gate 	if ( NULL == fds[i].lpoll_socketarg ) {
2570Sstevel@tonic-gate 	    pds[i].fd = NULL;
2580Sstevel@tonic-gate 	} else {
2590Sstevel@tonic-gate 	    pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg );
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	pds[i].in_flags = pds[i].out_flags = 0;
2620Sstevel@tonic-gate 	if ( fds[i].lpoll_fd >= 0 ) {
2630Sstevel@tonic-gate 	    for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) {
2640Sstevel@tonic-gate 		if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap )
2650Sstevel@tonic-gate 		    != 0 ) {
2660Sstevel@tonic-gate 			pds[i].in_flags |= prldap_eventmap[j].evm_nspr;
2670Sstevel@tonic-gate 		}
2680Sstevel@tonic-gate 	    }
2690Sstevel@tonic-gate 	}
2700Sstevel@tonic-gate 	fds[i].lpoll_revents = 0;	/* clear revents */
2710Sstevel@tonic-gate     }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate     /* call PR_Poll() to do the real work */
2740Sstevel@tonic-gate     rc = PR_Poll( pds, nfds,
2750Sstevel@tonic-gate 	    prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout ));
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate     /* populate LDAP info. based on NSPR results */
2780Sstevel@tonic-gate     for ( i = 0; i < nfds; ++i ) {
2790Sstevel@tonic-gate 	if ( pds[i].fd != NULL ) {
2800Sstevel@tonic-gate 	    for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) {
2810Sstevel@tonic-gate 		if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr )
2820Sstevel@tonic-gate 			!= 0 ) {
2830Sstevel@tonic-gate 		    fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap;
2840Sstevel@tonic-gate 		}
2850Sstevel@tonic-gate 	    }
2860Sstevel@tonic-gate 	}
2870Sstevel@tonic-gate     }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate     return( rc );
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate /*
2940Sstevel@tonic-gate  * Utility function to try one TCP connect()
2950Sstevel@tonic-gate  * Returns 1 if successful and -1 if not.  Sets the NSPR fd inside prsockp.
2960Sstevel@tonic-gate  */
2970Sstevel@tonic-gate static int
prldap_try_one_address(struct lextiof_socket_private * prsockp,PRNetAddr * addrp,int port,int timeout,unsigned long options)2980Sstevel@tonic-gate prldap_try_one_address( struct lextiof_socket_private *prsockp,
2990Sstevel@tonic-gate     PRNetAddr *addrp, int port, int timeout, unsigned long options )
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate     /*
3020Sstevel@tonic-gate      * Set up address and open a TCP socket:
3030Sstevel@tonic-gate      */
3040Sstevel@tonic-gate     if ( PR_SUCCESS != PR_SetNetAddr( PR_IpAddrNull, /* don't touch IP addr. */
3050Sstevel@tonic-gate 		PRLDAP_DEFAULT_ADDRESS_FAMILY, (PRUint16)port, addrp )) {
3060Sstevel@tonic-gate 	return( -1 );
3070Sstevel@tonic-gate     }
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate     if (( prsockp->prsock_prfd = PR_OpenTCPSocket(
3100Sstevel@tonic-gate 		PRLDAP_DEFAULT_ADDRESS_FAMILY )) == NULL ) {
3110Sstevel@tonic-gate 	return( -1 );
3120Sstevel@tonic-gate     }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate     /*
3150Sstevel@tonic-gate      * Set nonblocking option if requested:
3160Sstevel@tonic-gate      */
3170Sstevel@tonic-gate     if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) {
3180Sstevel@tonic-gate 	PRSocketOptionData	optdata;
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	optdata.option = PR_SockOpt_Nonblocking;
3210Sstevel@tonic-gate 	optdata.value.non_blocking = PR_TRUE;
3220Sstevel@tonic-gate 	if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata )
3230Sstevel@tonic-gate 		    != PR_SUCCESS ) {
3240Sstevel@tonic-gate 	    prldap_set_system_errno( prldap_prerr2errno());
3250Sstevel@tonic-gate 	    PR_Close( prsockp->prsock_prfd );
3260Sstevel@tonic-gate 	    return( -1 );
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate     }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
3310Sstevel@tonic-gate     {
3320Sstevel@tonic-gate 	char	buf[ 256 ], *p, *fmtstr;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) {
3350Sstevel@tonic-gate 		strcpy( buf, "conversion failed!" );
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 	if ( strncmp( buf, "::ffff:", 7 ) == 0 ) {
3380Sstevel@tonic-gate 		/* IPv4 address mapped into IPv6 address space */
3390Sstevel@tonic-gate 		p = buf + 7;
3400Sstevel@tonic-gate 		fmtstr = "prldap_try_one_address(): Trying %s:%d...\n";
3410Sstevel@tonic-gate 	} else {
3420Sstevel@tonic-gate 		p = buf;
3430Sstevel@tonic-gate 		fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n";
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 	fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port ));
3460Sstevel@tonic-gate     }
3470Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate     /*
3500Sstevel@tonic-gate      * Try to open the TCP connection itself:
3510Sstevel@tonic-gate      */
3520Sstevel@tonic-gate     if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp,
3530Sstevel@tonic-gate 		prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout ))) {
3540Sstevel@tonic-gate 	PR_Close( prsockp->prsock_prfd );
3550Sstevel@tonic-gate 	prsockp->prsock_prfd = NULL;
3560Sstevel@tonic-gate 	return( -1 );
3570Sstevel@tonic-gate     }
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate #ifdef PRLDAP_DEBUG
3600Sstevel@tonic-gate     fputs( "prldap_try_one_address(): Connected.\n", stderr );
3610Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate     /*
3640Sstevel@tonic-gate      * Success.  Return a valid file descriptor (1 is always valid)
3650Sstevel@tonic-gate      */
3660Sstevel@tonic-gate     return( 1 );
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate  * XXXmcs: At present, this code ignores the timeout when doing DNS lookups.
3720Sstevel@tonic-gate  */
3730Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_connect(const char * hostlist,int defport,int timeout,unsigned long options,struct lextiof_session_private * sessionarg,struct lextiof_socket_private ** socketargp,void ** dhost)3740Sstevel@tonic-gate prldap_connect( const char *hostlist, int defport, int timeout,
3750Sstevel@tonic-gate 	unsigned long options, struct lextiof_session_private *sessionarg,
3760Sstevel@tonic-gate 	struct lextiof_socket_private **socketargp
3770Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3780Sstevel@tonic-gate 	, void **dhost )
3790Sstevel@tonic-gate #else
3800Sstevel@tonic-gate 	)
3810Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate     int					rc, parse_err, port;
3840Sstevel@tonic-gate     char				*host, hbuf[ PR_NETDB_BUF_SIZE ];
3850Sstevel@tonic-gate     struct ldap_x_hostlist_status	*status;
3860Sstevel@tonic-gate     struct lextiof_socket_private	*prsockp;
3870Sstevel@tonic-gate     PRNetAddr				addr;
3880Sstevel@tonic-gate     PRHostEnt				hent;
3890Sstevel@tonic-gate #ifdef _SOLARIS_SDK
3900Sstevel@tonic-gate     char				*hostname = NULL;
3910Sstevel@tonic-gate     char				*nsldapi_strdup(char *);
3920Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate     if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
3950Sstevel@tonic-gate 	prldap_set_system_errno( EINVAL );
3960Sstevel@tonic-gate 	return( -1 );
3970Sstevel@tonic-gate     }
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate     if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) {
4000Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
4010Sstevel@tonic-gate 	return( -1 );
4020Sstevel@tonic-gate     }
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate     rc = -1;	/* pessimistic */
4050Sstevel@tonic-gate     for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port,
4060Sstevel@tonic-gate 		&status );
4070Sstevel@tonic-gate 		rc < 0 && LDAP_SUCCESS == parse_err && NULL != host;
4080Sstevel@tonic-gate 		parse_err = ldap_x_hostlist_next( &host, &port, status )) {
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) {
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		if ( PRLDAP_DEFAULT_ADDRESS_FAMILY == PR_AF_INET6 &&
4130Sstevel@tonic-gate 				PR_AF_INET == PR_NetAddrFamily( &addr )) {
4140Sstevel@tonic-gate 			PRUint32	ipv4ip = addr.inet.ip;
4150Sstevel@tonic-gate 			memset( &addr, 0, sizeof(addr));
4160Sstevel@tonic-gate 			PR_ConvertIPv4AddrToIPv6( ipv4ip, &addr.ipv6.ip );
4170Sstevel@tonic-gate 			addr.ipv6.family = PR_AF_INET6;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 		}
4200Sstevel@tonic-gate 	    rc = prldap_try_one_address( prsockp, &addr, port,
4210Sstevel@tonic-gate 			timeout, options );
4220Sstevel@tonic-gate 	} else {
4230Sstevel@tonic-gate 	    if ( PR_SUCCESS == PR_GetIPNodeByName( host,
4240Sstevel@tonic-gate 			PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT | PR_AI_ALL, hbuf,
4250Sstevel@tonic-gate 			sizeof( hbuf ), &hent )) {
4260Sstevel@tonic-gate 		PRIntn enumIndex = 0;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 		while ( rc < 0 && ( enumIndex = PR_EnumerateHostEnt(
4290Sstevel@tonic-gate 			    enumIndex, &hent, (PRUint16)port, &addr )) > 0 ) {
4300Sstevel@tonic-gate 		    rc = prldap_try_one_address( prsockp, &addr, port,
4310Sstevel@tonic-gate 				timeout, options );
4320Sstevel@tonic-gate 		}
4330Sstevel@tonic-gate 	    }
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate #ifdef _SOLARIS_SDK
437*10284SMilan.Jurik@Sun.COM 	if ( NULL != hostname ) {
438*10284SMilan.Jurik@Sun.COM 		ldap_memfree(hostname);
439*10284SMilan.Jurik@Sun.COM 		hostname = NULL;
440*10284SMilan.Jurik@Sun.COM 	}
441*10284SMilan.Jurik@Sun.COM 	if ( rc >= 0 ) {
442*10284SMilan.Jurik@Sun.COM 		hostname = nsldapi_strdup(host);
443*10284SMilan.Jurik@Sun.COM 	}
4440Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
4450Sstevel@tonic-gate 	ldap_memfree( host );
4460Sstevel@tonic-gate     }
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate     ldap_x_hostlist_statusfree( status );
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate     if ( rc < 0 ) {
4510Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
4520Sstevel@tonic-gate 	prldap_socket_arg_free( &prsockp );
4530Sstevel@tonic-gate     } else {
4540Sstevel@tonic-gate 	*socketargp = prsockp;
4550Sstevel@tonic-gate     }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate #ifdef _SOLARIS_SDK
4580Sstevel@tonic-gate     if ( NULL != hostname && NULL != dhost ) *dhost = hostname;
4590Sstevel@tonic-gate     else if ( NULL != hostname ) ldap_memfree(hostname);
4600Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate     return( rc );
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_close(int s,struct lextiof_socket_private * socketarg)4670Sstevel@tonic-gate prldap_close( int s, struct lextiof_socket_private *socketarg )
4680Sstevel@tonic-gate {
4690Sstevel@tonic-gate     int		rc;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate     rc = 0;
4720Sstevel@tonic-gate     if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) {
4730Sstevel@tonic-gate 	rc = -1;
4740Sstevel@tonic-gate 	prldap_set_system_errno( prldap_prerr2errno());
4750Sstevel@tonic-gate     }
4760Sstevel@tonic-gate     prldap_socket_arg_free( &socketarg );
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate     return( rc );
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate /*
4830Sstevel@tonic-gate  * LDAP session handle creation callback.
4840Sstevel@tonic-gate  *
4850Sstevel@tonic-gate  * Allocate a session argument if not already done, and then call the
4860Sstevel@tonic-gate  * thread's new handle function.
4870Sstevel@tonic-gate  */
4880Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_newhandle(LDAP * ld,struct lextiof_session_private * sessionarg)4890Sstevel@tonic-gate prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg )
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate     if ( NULL == sessionarg ) {
4930Sstevel@tonic-gate 	struct ldap_x_ext_io_fns	iofns;
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	memset( &iofns, 0, sizeof(iofns));
4960Sstevel@tonic-gate 	iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
4970Sstevel@tonic-gate 	if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
4980Sstevel@tonic-gate 		(void *)&iofns ) < 0 ) {
4990Sstevel@tonic-gate 	    return( ldap_get_lderrno( ld, NULL, NULL ));
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 	if ( NULL ==
5020Sstevel@tonic-gate 		( iofns.lextiof_session_arg = prldap_session_arg_alloc())) {
5030Sstevel@tonic-gate 	    return( LDAP_NO_MEMORY );
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 	if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
5060Sstevel@tonic-gate 		    (void *)&iofns ) < 0 ) {
5070Sstevel@tonic-gate 	    return( ldap_get_lderrno( ld, NULL, NULL ));
5080Sstevel@tonic-gate 	}
5090Sstevel@tonic-gate     }
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate     return( LDAP_SUCCESS );
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate /* only called/installed if shared is non-zero. */
5160Sstevel@tonic-gate static int LDAP_CALLBACK
prldap_shared_newhandle(LDAP * ld,struct lextiof_session_private * sessionarg)5170Sstevel@tonic-gate prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg )
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate     int		rc;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate     if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) {
5220Sstevel@tonic-gate 	rc = prldap_thread_new_handle( ld, sessionarg );
5230Sstevel@tonic-gate     }
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate     return( rc );
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate static void LDAP_CALLBACK
prldap_disposehandle(LDAP * ld,struct lextiof_session_private * sessionarg)5300Sstevel@tonic-gate prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg )
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate     prldap_session_arg_free( &sessionarg );
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate /* only called/installed if shared is non-zero */
5370Sstevel@tonic-gate static void LDAP_CALLBACK
prldap_shared_disposehandle(LDAP * ld,struct lextiof_session_private * sessionarg)5380Sstevel@tonic-gate prldap_shared_disposehandle( LDAP *ld,
5390Sstevel@tonic-gate 	struct lextiof_session_private *sessionarg )
5400Sstevel@tonic-gate {
5410Sstevel@tonic-gate     prldap_thread_dispose_handle( ld, sessionarg );
5420Sstevel@tonic-gate     prldap_disposehandle( ld, sessionarg );
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate  * Allocate a session argument.
5480Sstevel@tonic-gate  */
5490Sstevel@tonic-gate static PRLDAPIOSessionArg *
prldap_session_arg_alloc(void)5500Sstevel@tonic-gate prldap_session_arg_alloc( void )
5510Sstevel@tonic-gate {
5520Sstevel@tonic-gate     PRLDAPIOSessionArg		*prsessp;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate     prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg ));
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate     if ( NULL != prsessp ) {
5570Sstevel@tonic-gate 	/* copy global defaults to the new session handle */
5580Sstevel@tonic-gate 	prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout;
5590Sstevel@tonic-gate     }
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate     return( prsessp );
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate static void
prldap_session_arg_free(PRLDAPIOSessionArg ** prsesspp)5660Sstevel@tonic-gate prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp )
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate     if ( NULL != prsesspp && NULL != *prsesspp ) {
5690Sstevel@tonic-gate 	if ( NULL != (*prsesspp)->prsess_pollds ) {
5700Sstevel@tonic-gate 	    PR_Free( (*prsesspp)->prsess_pollds );
5710Sstevel@tonic-gate 	    (*prsesspp)->prsess_pollds = NULL;
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 	PR_Free( *prsesspp );
5740Sstevel@tonic-gate 	*prsesspp = NULL;
5750Sstevel@tonic-gate     }
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate /*
5800Sstevel@tonic-gate  * Given an LDAP session handle, retrieve a session argument.
5810Sstevel@tonic-gate  * Returns an LDAP error code.
5820Sstevel@tonic-gate  */
5830Sstevel@tonic-gate int
prldap_session_arg_from_ld(LDAP * ld,PRLDAPIOSessionArg ** sessargpp)5840Sstevel@tonic-gate prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp )
5850Sstevel@tonic-gate {
5860Sstevel@tonic-gate     struct ldap_x_ext_io_fns	iofns;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate     if ( NULL == ld || NULL == sessargpp ) {
5890Sstevel@tonic-gate 	/* XXXmcs: NULL ld's are not supported */
5900Sstevel@tonic-gate 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
5910Sstevel@tonic-gate 	return( LDAP_PARAM_ERROR );
5920Sstevel@tonic-gate     }
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate     memset( &iofns, 0, sizeof(iofns));
5950Sstevel@tonic-gate     iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
5960Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) {
5970Sstevel@tonic-gate 	return( ldap_get_lderrno( ld, NULL, NULL ));
5980Sstevel@tonic-gate     }
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate     if ( NULL == iofns.lextiof_session_arg ) {
6010Sstevel@tonic-gate 	ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6020Sstevel@tonic-gate 	return( LDAP_LOCAL_ERROR );
6030Sstevel@tonic-gate     }
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate     *sessargpp = iofns.lextiof_session_arg;
6060Sstevel@tonic-gate     return( LDAP_SUCCESS );
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate  * Given an LDAP session handle, retrieve a socket argument.
6120Sstevel@tonic-gate  * Returns an LDAP error code.
6130Sstevel@tonic-gate  */
6140Sstevel@tonic-gate int
prldap_socket_arg_from_ld(LDAP * ld,PRLDAPIOSocketArg ** sockargpp)6150Sstevel@tonic-gate prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp )
6160Sstevel@tonic-gate {
6170Sstevel@tonic-gate     Sockbuf *sbp;
6180Sstevel@tonic-gate     struct lber_x_ext_io_fns    extiofns;
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate     if ( NULL == ld || NULL == sockargpp ) {
6210Sstevel@tonic-gate         /* XXXmcs: NULL ld's are not supported */
6220Sstevel@tonic-gate         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
6230Sstevel@tonic-gate         return( LDAP_PARAM_ERROR );
6240Sstevel@tonic-gate     }
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) {
6270Sstevel@tonic-gate         return( ldap_get_lderrno( ld, NULL, NULL ));
6280Sstevel@tonic-gate     }
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate     memset( &extiofns, 0, sizeof(extiofns));
6310Sstevel@tonic-gate     extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
6320Sstevel@tonic-gate     if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS,
6330Sstevel@tonic-gate         (void *)&extiofns ) < 0 ) {
6340Sstevel@tonic-gate         return( ldap_get_lderrno( ld, NULL, NULL ));
6350Sstevel@tonic-gate     }
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate     if ( NULL == extiofns.lbextiofn_socket_arg ) {
6380Sstevel@tonic-gate         ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6390Sstevel@tonic-gate         return( LDAP_LOCAL_ERROR );
6400Sstevel@tonic-gate     }
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate     *sockargpp = extiofns.lbextiofn_socket_arg;
6430Sstevel@tonic-gate     return( LDAP_SUCCESS );
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate /*
6480Sstevel@tonic-gate  * Allocate a socket argument.
6490Sstevel@tonic-gate  */
6500Sstevel@tonic-gate static PRLDAPIOSocketArg *
prldap_socket_arg_alloc(PRLDAPIOSessionArg * sessionarg)6510Sstevel@tonic-gate prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg )
6520Sstevel@tonic-gate {
6530Sstevel@tonic-gate     PRLDAPIOSocketArg		*prsockp;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate     prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg ));
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate     if ( NULL != prsockp && NULL != sessionarg ) {
6580Sstevel@tonic-gate 	/* copy socket defaults from the session */
6590Sstevel@tonic-gate 	prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout;
6600Sstevel@tonic-gate     }
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate     return( prsockp );
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate static void
prldap_socket_arg_free(PRLDAPIOSocketArg ** prsockpp)6670Sstevel@tonic-gate prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp )
6680Sstevel@tonic-gate {
6690Sstevel@tonic-gate     if ( NULL != prsockpp && NULL != *prsockpp ) {
6700Sstevel@tonic-gate 	PR_Free( *prsockpp );
6710Sstevel@tonic-gate 	*prsockpp = NULL;
6720Sstevel@tonic-gate     }
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate static void *
prldap_safe_realloc(void * ptr,PRUint32 size)6770Sstevel@tonic-gate prldap_safe_realloc( void *ptr, PRUint32 size )
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate     void	*p;
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate     if ( NULL == ptr ) {
6820Sstevel@tonic-gate 	p = PR_Malloc( size );
6830Sstevel@tonic-gate     } else {
6840Sstevel@tonic-gate 	p = PR_Realloc( ptr, size );
6850Sstevel@tonic-gate     }
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate     return( p );
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate /* returns an LDAP result code */
6930Sstevel@tonic-gate int
prldap_set_io_max_timeout(PRLDAPIOSessionArg * prsessp,int io_max_timeout)6940Sstevel@tonic-gate prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout )
6950Sstevel@tonic-gate {
6960Sstevel@tonic-gate     int	rc = LDAP_SUCCESS;	/* optimistic */
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate     if ( NULL == prsessp ) {
6990Sstevel@tonic-gate 	prldap_default_io_max_timeout = io_max_timeout;
7000Sstevel@tonic-gate     } else {
7010Sstevel@tonic-gate 	prsessp->prsess_io_max_timeout = io_max_timeout;
7020Sstevel@tonic-gate     }
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate     return( rc );
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate /* returns an LDAP result code */
7090Sstevel@tonic-gate int
prldap_get_io_max_timeout(PRLDAPIOSessionArg * prsessp,int * io_max_timeoutp)7100Sstevel@tonic-gate prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp )
7110Sstevel@tonic-gate {
7120Sstevel@tonic-gate     int	rc = LDAP_SUCCESS;	/* optimistic */
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate     if ( NULL == io_max_timeoutp ) {
7150Sstevel@tonic-gate 	rc = LDAP_PARAM_ERROR;
7160Sstevel@tonic-gate     } else if ( NULL == prsessp ) {
7170Sstevel@tonic-gate 	*io_max_timeoutp = prldap_default_io_max_timeout;
7180Sstevel@tonic-gate     } else {
7190Sstevel@tonic-gate 	*io_max_timeoutp = prsessp->prsess_io_max_timeout;
7200Sstevel@tonic-gate     }
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate     return( rc );
7230Sstevel@tonic-gate }
724