From 6513e41cb75e64384f35470d59ad6a4f88092e82 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Sun, 3 Nov 2019 13:17:15 -0500 Subject: Issue #1258 - Part 2: Use binoc-central version of ldap --- ldap/c-sdk/libprldap/ldappr-io.c | 744 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 744 insertions(+) create mode 100644 ldap/c-sdk/libprldap/ldappr-io.c (limited to 'ldap/c-sdk/libprldap/ldappr-io.c') diff --git a/ldap/c-sdk/libprldap/ldappr-io.c b/ldap/c-sdk/libprldap/ldappr-io.c new file mode 100644 index 000000000..863545146 --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-io.c @@ -0,0 +1,744 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Extended I/O callback functions for libldap that use + * NSPR (Netscape Portable Runtime) I/O. + * + * High level strategy: we use the socket-specific arg to hold our own data + * structure that includes the NSPR file handle (PRFileDesc *), among other + * useful information. We use the default argument to hold an LDAP session + * handle specific data structure. + */ + +#include "ldappr-int.h" + +#define PRLDAP_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ + +/* + * Local function prototypes: + */ +static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout ); +static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds, + int timeout, struct lextiof_session_private *sessionarg ); +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 ); +static int LDAP_CALLBACK prldap_close( int s, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_newhandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static PRLDAPIOSessionArg *prldap_session_arg_alloc( void ); +static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ); +static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ); +static void *prldap_safe_realloc( void *ptr, PRUint32 size ); + + + +/* + * Local macros: + */ +/* given a socket-specific arg, return the corresponding PRFileDesc * */ +#define PRLDAP_GET_PRFD( socketarg ) \ + (((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd) + +/* + * Static variables. + */ +static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; + + +/* + * Install NSPR I/O functions into ld (if ld is NULL, they are installed + * as the default functions for new LDAP * handles). + * + * Returns 0 if all goes well and -1 if not. + */ +int +prldap_install_io_functions( LDAP *ld, int shared ) +{ + struct ldap_x_ext_io_fns iofns; + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + iofns.lextiof_read = prldap_read; + iofns.lextiof_write = prldap_write; + iofns.lextiof_poll = prldap_poll; + iofns.lextiof_connect = prldap_connect; + iofns.lextiof_close = prldap_close; + if ( shared ) { + iofns.lextiof_newhandle = prldap_shared_newhandle; + iofns.lextiof_disposehandle = prldap_shared_disposehandle; + } else { + iofns.lextiof_newhandle = prldap_newhandle; + iofns.lextiof_disposehandle = prldap_disposehandle; + } + if ( NULL != ld ) { + /* + * If we are dealing with a real ld, we allocate the session specific + * data structure now. If not allocated here, it will be allocated + * inside prldap_newhandle() or prldap_shared_newhandle(). + */ + if ( NULL == + ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { + ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + } else { + iofns.lextiof_session_arg = NULL; + } + + if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) { + prldap_session_arg_free( + (PRLDAPIOSessionArg **) &iofns.lextiof_session_arg ); + return( -1 ); + } + + return( 0 ); +} + + +static PRIntervalTime +prldap_timeout2it( int ms_timeout, int ms_maxtimeout ) +{ + PRIntervalTime prit; + + if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) { + prit = PR_INTERVAL_NO_WAIT; + } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) { + prit = PR_INTERVAL_NO_TIMEOUT; + } else { + prit = PR_MillisecondsToInterval( ms_timeout ); + } + + /* cap at maximum I/O timeout */ + if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) { + prit = LDAP_X_IO_TIMEOUT_NO_WAIT; + } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) { + if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout || + ms_timeout > ms_maxtimeout ) { + prit = PR_MillisecondsToInterval( ms_maxtimeout ); + } + } + +#ifdef PRLDAP_DEBUG + if ( PR_INTERVAL_NO_WAIT == prit ) { + fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" ); + } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) { + fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" ); + } else { + fprintf( stderr, "prldap_timeout2it: %dms\n", + PR_IntervalToMilliseconds(prit)); + } +#endif /* PRLDAP_DEBUG */ + + return( prit ); +} + + +static int LDAP_CALLBACK +prldap_read( int s, void *buf, int bufsize, + struct lextiof_socket_private *socketarg ) +{ + PRIntervalTime prit; + + prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, + socketarg->prsock_io_max_timeout ); + return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit )); +} + + +static int LDAP_CALLBACK +prldap_write( int s, const void *buf, int len, + struct lextiof_socket_private *socketarg ) +{ + PRIntervalTime prit; + char *ptr = (char *)buf; + int rest = len; + + prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, + socketarg->prsock_io_max_timeout ); + + while ( rest > 0 ) { + int rval; + if ( rest > PRLDAP_MAX_SEND_SIZE ) { + len = PRLDAP_MAX_SEND_SIZE; + } else { + len = rest; + } + /* + * Note the 4th parameter (flags) to PR_Send() has been obsoleted and + * must always be 0 + */ + rval = PR_Send( PRLDAP_GET_PRFD(socketarg), ptr, len, 0, prit ); + if ( 0 > rval ) { + return rval; + } + + if ( 0 == rval ) { + break; + } + + ptr += rval; + rest -= rval; + } + + return (int)( ptr - (char *)buf ); +} + + +struct prldap_eventmap_entry { + PRInt16 evm_nspr; /* corresponding NSPR PR_Poll() event */ + int evm_ldap; /* LDAP poll event */ +}; + +static struct prldap_eventmap_entry prldap_eventmap[] = { + { PR_POLL_READ, LDAP_X_POLLIN }, + { PR_POLL_EXCEPT, LDAP_X_POLLPRI }, + { PR_POLL_WRITE, LDAP_X_POLLOUT }, + { PR_POLL_ERR, LDAP_X_POLLERR }, + { PR_POLL_HUP, LDAP_X_POLLHUP }, + { PR_POLL_NVAL, LDAP_X_POLLNVAL }, +}; + +#define PRLDAP_EVENTMAP_ENTRIES \ + sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry ) + +static int LDAP_CALLBACK +prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout, + struct lextiof_session_private *sessionarg ) +{ + PRLDAPIOSessionArg *prsessp = sessionarg; + PRPollDesc *pds; + int i, j, rc; + + if ( NULL == prsessp ) { + prldap_set_system_errno( EINVAL ); + return( -1 ); + } + + /* allocate or resize NSPR poll descriptor array */ + if ( prsessp->prsess_pollds_count < nfds ) { + pds = prldap_safe_realloc( prsessp->prsess_pollds, + ( nfds + PRLDAP_POLL_ARRAY_GROWTH ) + * sizeof( PRPollDesc )); + if ( NULL == pds ) { + prldap_set_system_errno( prldap_prerr2errno()); + return( -1 ); + } + prsessp->prsess_pollds = pds; + prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH; + } else { + pds = prsessp->prsess_pollds; + } + + /* populate NSPR poll info. based on LDAP info. */ + for ( i = 0; i < nfds; ++i ) { + if ( NULL == fds[i].lpoll_socketarg ) { + pds[i].fd = NULL; + } else { + pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg ); + } + pds[i].in_flags = pds[i].out_flags = 0; + if ( fds[i].lpoll_fd >= 0 ) { + for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { + if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap ) + != 0 ) { + pds[i].in_flags |= prldap_eventmap[j].evm_nspr; + } + } + } + fds[i].lpoll_revents = 0; /* clear revents */ + } + + /* call PR_Poll() to do the real work */ + rc = PR_Poll( pds, nfds, + prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout )); + + /* populate LDAP info. based on NSPR results */ + for ( i = 0; i < nfds; ++i ) { + if ( pds[i].fd != NULL ) { + for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { + if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr ) + != 0 ) { + fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap; + } + } + } + } + + return( rc ); +} + + +/* + * Utility function to try one TCP connect() + * Returns 1 if successful and -1 if not. Sets the NSPR fd inside prsockp. + */ +static int +prldap_try_one_address( struct lextiof_socket_private *prsockp, + PRNetAddr *addrp, int timeout, unsigned long options ) +{ + /* + * Open a TCP socket: + */ + if (( prsockp->prsock_prfd = PR_OpenTCPSocket( + PR_NetAddrFamily(addrp) )) == NULL ) { + return( -1 ); + } + + /* + * Set nonblocking option if requested: + */ + if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) { + PRSocketOptionData optdata; + + optdata.option = PR_SockOpt_Nonblocking; + optdata.value.non_blocking = PR_TRUE; + if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata ) + != PR_SUCCESS ) { + prldap_set_system_errno( prldap_prerr2errno()); + PR_Close( prsockp->prsock_prfd ); + return( -1 ); + } + } + +#ifdef PRLDAP_DEBUG + { + char buf[ 256 ], *p, *fmtstr; + + if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) { + strcpy( buf, "conversion failed!" ); + } + if ( strncmp( buf, "::ffff:", 7 ) == 0 ) { + /* IPv4 address mapped into IPv6 address space */ + p = buf + 7; + fmtstr = "prldap_try_one_address(): Trying %s:%d...\n"; + } else { + p = buf; + fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n"; + } + fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port )); + } +#endif /* PRLDAP_DEBUG */ + + /* + * Try to open the TCP connection itself: + */ + if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp, + prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout )) + && PR_IN_PROGRESS_ERROR != PR_GetError() ) { + PR_Close( prsockp->prsock_prfd ); + prsockp->prsock_prfd = NULL; + return( -1 ); + } + +#ifdef PRLDAP_DEBUG + fputs( "prldap_try_one_address(): Connected.\n", stderr ); +#endif /* PRLDAP_DEBUG */ + + /* + * Success. Return a valid file descriptor (1 is always valid) + */ + return( 1 ); +} + + +/* + * XXXmcs: At present, this code ignores the timeout when doing DNS lookups. + */ +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 ) +{ + int rc, parse_err, port; + char *host; + struct ldap_x_hostlist_status *status; + struct lextiof_socket_private *prsockp; + PRNetAddr addr; + PRAddrInfo *infop = NULL; + + if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { + prldap_set_system_errno( EINVAL ); + return( -1 ); + } + + if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) { + prldap_set_system_errno( prldap_prerr2errno()); + return( -1 ); + } + + rc = -1; /* pessimistic */ + for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, + &status ); + rc < 0 && LDAP_SUCCESS == parse_err && NULL != host; + parse_err = ldap_x_hostlist_next( &host, &port, status )) { + /* + * First, call PR_GetAddrInfoByName; PR_GetAddrInfoByName could + * support both IPv4 and IPv6 addresses depending upon the system's + * configuration. All available addresses are returned and each of + * them is examined in prldap_try_one_address till it succeeds. + * Then, try converting the string address, in case the string + * address was not successfully handled in PR_GetAddrInfoByName. + */ + if ( NULL != ( infop = + PR_GetAddrInfoByName( host, PR_AF_UNSPEC, + (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME) ))) { + void *enump = NULL; + do { + memset( &addr, 0, sizeof( addr )); + enump = PR_EnumerateAddrInfo( enump, infop, port, &addr ); + if ( NULL == enump ) { + break; + } + rc = prldap_try_one_address( prsockp, &addr, timeout, options ); + } while ( rc < 0 ); + PR_FreeAddrInfo( infop ); + } else if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) { + PRLDAP_SET_PORT( &addr, port ); + rc = prldap_try_one_address( prsockp, &addr, timeout, options ); + } + ldap_memfree( host ); + } + + if ( host ) { + ldap_memfree( host ); + } + ldap_x_hostlist_statusfree( status ); + + if ( rc < 0 ) { + prldap_set_system_errno( prldap_prerr2errno()); + prldap_socket_arg_free( &prsockp ); + } else { + *socketargp = prsockp; + } + + return( rc ); +} + + +static int LDAP_CALLBACK +prldap_close( int s, struct lextiof_socket_private *socketarg ) +{ + int rc; + + rc = 0; + if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) { + rc = -1; + prldap_set_system_errno( prldap_prerr2errno()); + } + prldap_socket_arg_free( &socketarg ); + + return( rc ); +} + + +/* + * LDAP session handle creation callback. + * + * Allocate a session argument if not already done, and then call the + * thread's new handle function. + */ +static int LDAP_CALLBACK +prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + + if ( NULL == sessionarg ) { + struct ldap_x_ext_io_fns iofns; + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, + (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + if ( NULL == + ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { + return( LDAP_NO_MEMORY ); + } + if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, + (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + } + + return( LDAP_SUCCESS ); +} + + +/* only called/installed if shared is non-zero. */ +static int LDAP_CALLBACK +prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + int rc; + + if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) { + rc = prldap_thread_new_handle( ld, sessionarg ); + } + + return( rc ); +} + + +static void LDAP_CALLBACK +prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + prldap_session_arg_free( &sessionarg ); +} + + +/* only called/installed if shared is non-zero */ +static void LDAP_CALLBACK +prldap_shared_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ) +{ + prldap_thread_dispose_handle( ld, sessionarg ); + prldap_disposehandle( ld, sessionarg ); +} + + +/* + * Allocate a session argument. + */ +static PRLDAPIOSessionArg * +prldap_session_arg_alloc( void ) +{ + PRLDAPIOSessionArg *prsessp; + + prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg )); + + if ( NULL != prsessp ) { + /* copy global defaults to the new session handle */ + prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout; + } + + return( prsessp ); +} + + +static void +prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ) +{ + if ( NULL != prsesspp && NULL != *prsesspp ) { + if ( NULL != (*prsesspp)->prsess_pollds ) { + PR_Free( (*prsesspp)->prsess_pollds ); + (*prsesspp)->prsess_pollds = NULL; + } + PR_Free( *prsesspp ); + *prsesspp = NULL; + } +} + + +/* + * Given an LDAP session handle, retrieve a session argument. + * Returns an LDAP error code. + */ +int +prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ) +{ + struct ldap_x_ext_io_fns iofns; + + if ( NULL == ld || NULL == sessargpp ) { + /* XXXmcs: NULL ld's are not supported */ + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + if ( NULL == iofns.lextiof_session_arg ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + *sessargpp = iofns.lextiof_session_arg; + return( LDAP_SUCCESS ); +} + + +/* + * Given an LDAP session handle, retrieve a socket argument. + * Returns an LDAP error code. + */ +int +prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ) +{ + Sockbuf *sbp; + struct lber_x_ext_io_fns extiofns; + + if ( NULL == ld || NULL == sockargpp ) { + /* XXXmcs: NULL ld's are not supported */ + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + memset( &extiofns, 0, sizeof(extiofns)); + extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&extiofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + if ( NULL == extiofns.lbextiofn_socket_arg ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + *sockargpp = extiofns.lbextiofn_socket_arg; + return( LDAP_SUCCESS ); +} + + +/* + * Allocate a socket argument. + */ +PRLDAPIOSocketArg * +prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ) +{ + PRLDAPIOSocketArg *prsockp; + + prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg )); + + if ( NULL != prsockp && NULL != sessionarg ) { + /* copy socket defaults from the session */ + prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout; + } + + return( prsockp ); +} + + +static void +prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ) +{ + if ( NULL != prsockpp && NULL != *prsockpp ) { + PR_Free( *prsockpp ); + *prsockpp = NULL; + } +} + + +static void * +prldap_safe_realloc( void *ptr, PRUint32 size ) +{ + void *p; + + if ( NULL == ptr ) { + p = PR_Malloc( size ); + } else { + p = PR_Realloc( ptr, size ); + } + + return( p ); +} + + + +/* returns an LDAP result code */ +int +prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + + if ( NULL == prsessp ) { + prldap_default_io_max_timeout = io_max_timeout; + } else { + prsessp->prsess_io_max_timeout = io_max_timeout; + } + + return( rc ); +} + + +/* returns an LDAP result code */ +int +prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + + if ( NULL == io_max_timeoutp ) { + rc = LDAP_PARAM_ERROR; + } else if ( NULL == prsessp ) { + *io_max_timeoutp = prldap_default_io_max_timeout; + } else { + *io_max_timeoutp = prsessp->prsess_io_max_timeout; + } + + return( rc ); +} + +/* Check if NSPR layer has been installed for a LDAP session. + * Simply check whether prldap_connect() I/O function is installed + */ +PRBool +prldap_is_installed( LDAP *ld ) +{ + struct ldap_x_ext_io_fns iofns; + + /* Retrieve current I/O functions */ + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ld == NULL || ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) + != 0 || iofns.lextiof_connect != prldap_connect ) + { + return( PR_FALSE ); + } + + return( PR_TRUE ); +} + -- cgit v1.2.3