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