17c478bd9Sstevel@tonic-gate /* 2*e944850bSMilan Jurik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* 77c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 87c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 97c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 107c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 137c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 147c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing 157c478bd9Sstevel@tonic-gate * rights and limitations under the License. 167c478bd9Sstevel@tonic-gate * 177c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 187c478bd9Sstevel@tonic-gate * March 31, 1998. 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 217c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 227c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 237c478bd9Sstevel@tonic-gate * Rights Reserved. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * Contributor(s): 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Extended I/O callback functions for libldap that use 307c478bd9Sstevel@tonic-gate * NSPR (Netscape Portable Runtime) I/O. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * High level strategy: we use the socket-specific arg to hold our own data 337c478bd9Sstevel@tonic-gate * structure that includes the NSPR file handle (PRFileDesc *), among other 347c478bd9Sstevel@tonic-gate * useful information. We use the default argument to hold an LDAP session 357c478bd9Sstevel@tonic-gate * handle specific data structure. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "ldappr-int.h" 397c478bd9Sstevel@tonic-gate #include <string.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #define PRLDAP_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * Local function prototypes: 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout ); 477c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize, 487c478bd9Sstevel@tonic-gate struct lextiof_socket_private *socketarg ); 497c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len, 507c478bd9Sstevel@tonic-gate struct lextiof_socket_private *socketarg ); 517c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds, 527c478bd9Sstevel@tonic-gate int timeout, struct lextiof_session_private *sessionarg ); 537c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_connect( const char *hostlist, int defport, 547c478bd9Sstevel@tonic-gate int timeout, unsigned long options, 557c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg, 567c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp 577c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 587c478bd9Sstevel@tonic-gate , void **dhost ); 597c478bd9Sstevel@tonic-gate #else 607c478bd9Sstevel@tonic-gate ); 617c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 627c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_close( int s, 637c478bd9Sstevel@tonic-gate struct lextiof_socket_private *socketarg ); 647c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_newhandle( LDAP *ld, 657c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ); 667c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld, 677c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ); 687c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld, 697c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ); 707c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld, 717c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ); 727c478bd9Sstevel@tonic-gate static PRLDAPIOSessionArg *prldap_session_arg_alloc( void ); 737c478bd9Sstevel@tonic-gate static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ); 747c478bd9Sstevel@tonic-gate static PRLDAPIOSocketArg *prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ); 757c478bd9Sstevel@tonic-gate static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ); 767c478bd9Sstevel@tonic-gate static void *prldap_safe_realloc( void *ptr, PRUint32 size ); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Local macros: 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate /* given a socket-specific arg, return the corresponding PRFileDesc * */ 847c478bd9Sstevel@tonic-gate #define PRLDAP_GET_PRFD( socketarg ) \ 857c478bd9Sstevel@tonic-gate (((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd) 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * Static variables. 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Install NSPR I/O functions into ld (if ld is NULL, they are installed 947c478bd9Sstevel@tonic-gate * as the default functions for new LDAP * handles). 957c478bd9Sstevel@tonic-gate * 967c478bd9Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not. 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate int 997c478bd9Sstevel@tonic-gate prldap_install_io_functions( LDAP *ld, int shared ) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 1047c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 1057c478bd9Sstevel@tonic-gate iofns.lextiof_read = prldap_read; 1067c478bd9Sstevel@tonic-gate iofns.lextiof_write = prldap_write; 1077c478bd9Sstevel@tonic-gate iofns.lextiof_poll = prldap_poll; 1087c478bd9Sstevel@tonic-gate iofns.lextiof_connect = prldap_connect; 1097c478bd9Sstevel@tonic-gate iofns.lextiof_close = prldap_close; 1107c478bd9Sstevel@tonic-gate if ( shared ) { 1117c478bd9Sstevel@tonic-gate iofns.lextiof_newhandle = prldap_shared_newhandle; 1127c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle = prldap_shared_disposehandle; 1137c478bd9Sstevel@tonic-gate } else { 1147c478bd9Sstevel@tonic-gate iofns.lextiof_newhandle = prldap_newhandle; 1157c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle = prldap_disposehandle; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate if ( NULL != ld ) { 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * If we are dealing with a real ld, we allocate the session specific 1207c478bd9Sstevel@tonic-gate * data structure now. If not allocated here, it will be allocated 1217c478bd9Sstevel@tonic-gate * inside prldap_newhandle() or prldap_shared_newhandle(). 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate if ( NULL == 1247c478bd9Sstevel@tonic-gate ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { 1257c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); 1267c478bd9Sstevel@tonic-gate return( -1 ); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate } else { 1297c478bd9Sstevel@tonic-gate iofns.lextiof_session_arg = NULL; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) { 1337c478bd9Sstevel@tonic-gate prldap_session_arg_free( 1347c478bd9Sstevel@tonic-gate (PRLDAPIOSessionArg **) &iofns.lextiof_session_arg ); 1357c478bd9Sstevel@tonic-gate return( -1 ); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate return( 0 ); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate static PRIntervalTime 1437c478bd9Sstevel@tonic-gate prldap_timeout2it( int ms_timeout, int ms_maxtimeout ) 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate PRIntervalTime prit; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) { 1487c478bd9Sstevel@tonic-gate prit = PR_INTERVAL_NO_WAIT; 1497c478bd9Sstevel@tonic-gate } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) { 1507c478bd9Sstevel@tonic-gate prit = PR_INTERVAL_NO_TIMEOUT; 1517c478bd9Sstevel@tonic-gate } else { 1527c478bd9Sstevel@tonic-gate prit = PR_MillisecondsToInterval( ms_timeout ); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* cap at maximum I/O timeout */ 1567c478bd9Sstevel@tonic-gate if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) { 1577c478bd9Sstevel@tonic-gate prit = LDAP_X_IO_TIMEOUT_NO_WAIT; 1587c478bd9Sstevel@tonic-gate } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) { 1597c478bd9Sstevel@tonic-gate if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout || 1607c478bd9Sstevel@tonic-gate ms_timeout > ms_maxtimeout ) { 1617c478bd9Sstevel@tonic-gate prit = PR_MillisecondsToInterval( ms_maxtimeout ); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG 1667c478bd9Sstevel@tonic-gate if ( PR_INTERVAL_NO_WAIT == prit ) { 1677c478bd9Sstevel@tonic-gate fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" ); 1687c478bd9Sstevel@tonic-gate } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) { 1697c478bd9Sstevel@tonic-gate fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" ); 1707c478bd9Sstevel@tonic-gate } else { 1717c478bd9Sstevel@tonic-gate fprintf( stderr, "prldap_timeout2it: %dms\n", 1727c478bd9Sstevel@tonic-gate PR_IntervalToMilliseconds(prit)); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */ 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate return( prit ); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 1817c478bd9Sstevel@tonic-gate prldap_read( int s, void *buf, int bufsize, 1827c478bd9Sstevel@tonic-gate struct lextiof_socket_private *socketarg ) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate PRIntervalTime prit; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, 1877c478bd9Sstevel@tonic-gate socketarg->prsock_io_max_timeout ); 1887c478bd9Sstevel@tonic-gate return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit )); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 1937c478bd9Sstevel@tonic-gate prldap_write( int s, const void *buf, int len, 1947c478bd9Sstevel@tonic-gate struct lextiof_socket_private *socketarg ) 1957c478bd9Sstevel@tonic-gate { 1967c478bd9Sstevel@tonic-gate PRIntervalTime prit; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, 1997c478bd9Sstevel@tonic-gate socketarg->prsock_io_max_timeout ); 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Note the 4th parameter (flags) to PR_Send() has been obsoleted and 2037c478bd9Sstevel@tonic-gate * must always be 0 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate return( PR_Send( PRLDAP_GET_PRFD(socketarg), buf, len, 0, prit )); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate struct prldap_eventmap_entry { 2107c478bd9Sstevel@tonic-gate PRInt16 evm_nspr; /* corresponding NSPR PR_Poll() event */ 2117c478bd9Sstevel@tonic-gate int evm_ldap; /* LDAP poll event */ 2127c478bd9Sstevel@tonic-gate }; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate static struct prldap_eventmap_entry prldap_eventmap[] = { 2157c478bd9Sstevel@tonic-gate { PR_POLL_READ, LDAP_X_POLLIN }, 2167c478bd9Sstevel@tonic-gate { PR_POLL_EXCEPT, LDAP_X_POLLPRI }, 2177c478bd9Sstevel@tonic-gate { PR_POLL_WRITE, LDAP_X_POLLOUT }, 2187c478bd9Sstevel@tonic-gate { PR_POLL_ERR, LDAP_X_POLLERR }, 2197c478bd9Sstevel@tonic-gate { PR_POLL_HUP, LDAP_X_POLLHUP }, 2207c478bd9Sstevel@tonic-gate { PR_POLL_NVAL, LDAP_X_POLLNVAL }, 2217c478bd9Sstevel@tonic-gate }; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate #define PRLDAP_EVENTMAP_ENTRIES \ 2247c478bd9Sstevel@tonic-gate sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry ) 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 2277c478bd9Sstevel@tonic-gate prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout, 2287c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ) 2297c478bd9Sstevel@tonic-gate { 2307c478bd9Sstevel@tonic-gate PRLDAPIOSessionArg *prsessp = sessionarg; 2317c478bd9Sstevel@tonic-gate PRPollDesc *pds; 2327c478bd9Sstevel@tonic-gate int i, j, rc; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if ( NULL == prsessp ) { 2357c478bd9Sstevel@tonic-gate prldap_set_system_errno( EINVAL ); 2367c478bd9Sstevel@tonic-gate return( -1 ); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* allocate or resize NSPR poll descriptor array */ 2407c478bd9Sstevel@tonic-gate if ( prsessp->prsess_pollds_count < nfds ) { 2417c478bd9Sstevel@tonic-gate pds = prldap_safe_realloc( prsessp->prsess_pollds, 2427c478bd9Sstevel@tonic-gate ( nfds + PRLDAP_POLL_ARRAY_GROWTH ) 2437c478bd9Sstevel@tonic-gate * sizeof( PRPollDesc )); 2447c478bd9Sstevel@tonic-gate if ( NULL == pds ) { 2457c478bd9Sstevel@tonic-gate prldap_set_system_errno( prldap_prerr2errno()); 2467c478bd9Sstevel@tonic-gate return( -1 ); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate prsessp->prsess_pollds = pds; 2497c478bd9Sstevel@tonic-gate prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH; 2507c478bd9Sstevel@tonic-gate } else { 2517c478bd9Sstevel@tonic-gate pds = prsessp->prsess_pollds; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* populate NSPR poll info. based on LDAP info. */ 2557c478bd9Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) { 2567c478bd9Sstevel@tonic-gate if ( NULL == fds[i].lpoll_socketarg ) { 2577c478bd9Sstevel@tonic-gate pds[i].fd = NULL; 2587c478bd9Sstevel@tonic-gate } else { 2597c478bd9Sstevel@tonic-gate pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg ); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate pds[i].in_flags = pds[i].out_flags = 0; 2627c478bd9Sstevel@tonic-gate if ( fds[i].lpoll_fd >= 0 ) { 2637c478bd9Sstevel@tonic-gate for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { 2647c478bd9Sstevel@tonic-gate if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap ) 2657c478bd9Sstevel@tonic-gate != 0 ) { 2667c478bd9Sstevel@tonic-gate pds[i].in_flags |= prldap_eventmap[j].evm_nspr; 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate fds[i].lpoll_revents = 0; /* clear revents */ 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* call PR_Poll() to do the real work */ 2747c478bd9Sstevel@tonic-gate rc = PR_Poll( pds, nfds, 2757c478bd9Sstevel@tonic-gate prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout )); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* populate LDAP info. based on NSPR results */ 2787c478bd9Sstevel@tonic-gate for ( i = 0; i < nfds; ++i ) { 2797c478bd9Sstevel@tonic-gate if ( pds[i].fd != NULL ) { 2807c478bd9Sstevel@tonic-gate for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { 2817c478bd9Sstevel@tonic-gate if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr ) 2827c478bd9Sstevel@tonic-gate != 0 ) { 2837c478bd9Sstevel@tonic-gate fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate return( rc ); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * Utility function to try one TCP connect() 2957c478bd9Sstevel@tonic-gate * Returns 1 if successful and -1 if not. Sets the NSPR fd inside prsockp. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate static int 2987c478bd9Sstevel@tonic-gate prldap_try_one_address( struct lextiof_socket_private *prsockp, 2997c478bd9Sstevel@tonic-gate PRNetAddr *addrp, int port, int timeout, unsigned long options ) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Set up address and open a TCP socket: 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate if ( PR_SUCCESS != PR_SetNetAddr( PR_IpAddrNull, /* don't touch IP addr. */ 3057c478bd9Sstevel@tonic-gate PRLDAP_DEFAULT_ADDRESS_FAMILY, (PRUint16)port, addrp )) { 3067c478bd9Sstevel@tonic-gate return( -1 ); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (( prsockp->prsock_prfd = PR_OpenTCPSocket( 3107c478bd9Sstevel@tonic-gate PRLDAP_DEFAULT_ADDRESS_FAMILY )) == NULL ) { 3117c478bd9Sstevel@tonic-gate return( -1 ); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Set nonblocking option if requested: 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) { 3187c478bd9Sstevel@tonic-gate PRSocketOptionData optdata; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate optdata.option = PR_SockOpt_Nonblocking; 3217c478bd9Sstevel@tonic-gate optdata.value.non_blocking = PR_TRUE; 3227c478bd9Sstevel@tonic-gate if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata ) 3237c478bd9Sstevel@tonic-gate != PR_SUCCESS ) { 3247c478bd9Sstevel@tonic-gate prldap_set_system_errno( prldap_prerr2errno()); 3257c478bd9Sstevel@tonic-gate PR_Close( prsockp->prsock_prfd ); 3267c478bd9Sstevel@tonic-gate return( -1 ); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate char buf[ 256 ], *p, *fmtstr; 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) { 3357c478bd9Sstevel@tonic-gate strcpy( buf, "conversion failed!" ); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate if ( strncmp( buf, "::ffff:", 7 ) == 0 ) { 3387c478bd9Sstevel@tonic-gate /* IPv4 address mapped into IPv6 address space */ 3397c478bd9Sstevel@tonic-gate p = buf + 7; 3407c478bd9Sstevel@tonic-gate fmtstr = "prldap_try_one_address(): Trying %s:%d...\n"; 3417c478bd9Sstevel@tonic-gate } else { 3427c478bd9Sstevel@tonic-gate p = buf; 3437c478bd9Sstevel@tonic-gate fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n"; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port )); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */ 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Try to open the TCP connection itself: 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp, 3537c478bd9Sstevel@tonic-gate prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout ))) { 3547c478bd9Sstevel@tonic-gate PR_Close( prsockp->prsock_prfd ); 3557c478bd9Sstevel@tonic-gate prsockp->prsock_prfd = NULL; 3567c478bd9Sstevel@tonic-gate return( -1 ); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate #ifdef PRLDAP_DEBUG 3607c478bd9Sstevel@tonic-gate fputs( "prldap_try_one_address(): Connected.\n", stderr ); 3617c478bd9Sstevel@tonic-gate #endif /* PRLDAP_DEBUG */ 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Success. Return a valid file descriptor (1 is always valid) 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate return( 1 ); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * XXXmcs: At present, this code ignores the timeout when doing DNS lookups. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 3747c478bd9Sstevel@tonic-gate prldap_connect( const char *hostlist, int defport, int timeout, 3757c478bd9Sstevel@tonic-gate unsigned long options, struct lextiof_session_private *sessionarg, 3767c478bd9Sstevel@tonic-gate struct lextiof_socket_private **socketargp 3777c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 3787c478bd9Sstevel@tonic-gate , void **dhost ) 3797c478bd9Sstevel@tonic-gate #else 3807c478bd9Sstevel@tonic-gate ) 3817c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate int rc, parse_err, port; 3847c478bd9Sstevel@tonic-gate char *host, hbuf[ PR_NETDB_BUF_SIZE ]; 3857c478bd9Sstevel@tonic-gate struct ldap_x_hostlist_status *status; 3867c478bd9Sstevel@tonic-gate struct lextiof_socket_private *prsockp; 3877c478bd9Sstevel@tonic-gate PRNetAddr addr; 3887c478bd9Sstevel@tonic-gate PRHostEnt hent; 3897c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 3907c478bd9Sstevel@tonic-gate char *hostname = NULL; 3917c478bd9Sstevel@tonic-gate char *nsldapi_strdup(char *); 3927c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { 3957c478bd9Sstevel@tonic-gate prldap_set_system_errno( EINVAL ); 3967c478bd9Sstevel@tonic-gate return( -1 ); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) { 4007c478bd9Sstevel@tonic-gate prldap_set_system_errno( prldap_prerr2errno()); 4017c478bd9Sstevel@tonic-gate return( -1 ); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate rc = -1; /* pessimistic */ 4057c478bd9Sstevel@tonic-gate for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, 4067c478bd9Sstevel@tonic-gate &status ); 4077c478bd9Sstevel@tonic-gate rc < 0 && LDAP_SUCCESS == parse_err && NULL != host; 4087c478bd9Sstevel@tonic-gate parse_err = ldap_x_hostlist_next( &host, &port, status )) { 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) { 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if ( PRLDAP_DEFAULT_ADDRESS_FAMILY == PR_AF_INET6 && 4137c478bd9Sstevel@tonic-gate PR_AF_INET == PR_NetAddrFamily( &addr )) { 4147c478bd9Sstevel@tonic-gate PRUint32 ipv4ip = addr.inet.ip; 4157c478bd9Sstevel@tonic-gate memset( &addr, 0, sizeof(addr)); 4167c478bd9Sstevel@tonic-gate PR_ConvertIPv4AddrToIPv6( ipv4ip, &addr.ipv6.ip ); 4177c478bd9Sstevel@tonic-gate addr.ipv6.family = PR_AF_INET6; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate rc = prldap_try_one_address( prsockp, &addr, port, 4217c478bd9Sstevel@tonic-gate timeout, options ); 4227c478bd9Sstevel@tonic-gate } else { 4237c478bd9Sstevel@tonic-gate if ( PR_SUCCESS == PR_GetIPNodeByName( host, 4247c478bd9Sstevel@tonic-gate PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT | PR_AI_ALL, hbuf, 4257c478bd9Sstevel@tonic-gate sizeof( hbuf ), &hent )) { 4267c478bd9Sstevel@tonic-gate PRIntn enumIndex = 0; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate while ( rc < 0 && ( enumIndex = PR_EnumerateHostEnt( 4297c478bd9Sstevel@tonic-gate enumIndex, &hent, (PRUint16)port, &addr )) > 0 ) { 4307c478bd9Sstevel@tonic-gate rc = prldap_try_one_address( prsockp, &addr, port, 4317c478bd9Sstevel@tonic-gate timeout, options ); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 437*e944850bSMilan Jurik if ( NULL != hostname ) { 438*e944850bSMilan Jurik ldap_memfree(hostname); 439*e944850bSMilan Jurik hostname = NULL; 440*e944850bSMilan Jurik } 441*e944850bSMilan Jurik if ( rc >= 0 ) { 442*e944850bSMilan Jurik hostname = nsldapi_strdup(host); 443*e944850bSMilan Jurik } 4447c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 4457c478bd9Sstevel@tonic-gate ldap_memfree( host ); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate ldap_x_hostlist_statusfree( status ); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if ( rc < 0 ) { 4517c478bd9Sstevel@tonic-gate prldap_set_system_errno( prldap_prerr2errno()); 4527c478bd9Sstevel@tonic-gate prldap_socket_arg_free( &prsockp ); 4537c478bd9Sstevel@tonic-gate } else { 4547c478bd9Sstevel@tonic-gate *socketargp = prsockp; 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate #ifdef _SOLARIS_SDK 4587c478bd9Sstevel@tonic-gate if ( NULL != hostname && NULL != dhost ) *dhost = hostname; 4597c478bd9Sstevel@tonic-gate else if ( NULL != hostname ) ldap_memfree(hostname); 4607c478bd9Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate return( rc ); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 4677c478bd9Sstevel@tonic-gate prldap_close( int s, struct lextiof_socket_private *socketarg ) 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate int rc; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate rc = 0; 4727c478bd9Sstevel@tonic-gate if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) { 4737c478bd9Sstevel@tonic-gate rc = -1; 4747c478bd9Sstevel@tonic-gate prldap_set_system_errno( prldap_prerr2errno()); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate prldap_socket_arg_free( &socketarg ); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate return( rc ); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * LDAP session handle creation callback. 4847c478bd9Sstevel@tonic-gate * 4857c478bd9Sstevel@tonic-gate * Allocate a session argument if not already done, and then call the 4867c478bd9Sstevel@tonic-gate * thread's new handle function. 4877c478bd9Sstevel@tonic-gate */ 4887c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 4897c478bd9Sstevel@tonic-gate prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if ( NULL == sessionarg ) { 4937c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 4967c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 4977c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, 4987c478bd9Sstevel@tonic-gate (void *)&iofns ) < 0 ) { 4997c478bd9Sstevel@tonic-gate return( ldap_get_lderrno( ld, NULL, NULL )); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate if ( NULL == 5027c478bd9Sstevel@tonic-gate ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { 5037c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY ); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, 5067c478bd9Sstevel@tonic-gate (void *)&iofns ) < 0 ) { 5077c478bd9Sstevel@tonic-gate return( ldap_get_lderrno( ld, NULL, NULL )); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS ); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* only called/installed if shared is non-zero. */ 5167c478bd9Sstevel@tonic-gate static int LDAP_CALLBACK 5177c478bd9Sstevel@tonic-gate prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate int rc; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) { 5227c478bd9Sstevel@tonic-gate rc = prldap_thread_new_handle( ld, sessionarg ); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate return( rc ); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK 5307c478bd9Sstevel@tonic-gate prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg ) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate prldap_session_arg_free( &sessionarg ); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* only called/installed if shared is non-zero */ 5377c478bd9Sstevel@tonic-gate static void LDAP_CALLBACK 5387c478bd9Sstevel@tonic-gate prldap_shared_disposehandle( LDAP *ld, 5397c478bd9Sstevel@tonic-gate struct lextiof_session_private *sessionarg ) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate prldap_thread_dispose_handle( ld, sessionarg ); 5427c478bd9Sstevel@tonic-gate prldap_disposehandle( ld, sessionarg ); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * Allocate a session argument. 5487c478bd9Sstevel@tonic-gate */ 5497c478bd9Sstevel@tonic-gate static PRLDAPIOSessionArg * 5507c478bd9Sstevel@tonic-gate prldap_session_arg_alloc( void ) 5517c478bd9Sstevel@tonic-gate { 5527c478bd9Sstevel@tonic-gate PRLDAPIOSessionArg *prsessp; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg )); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if ( NULL != prsessp ) { 5577c478bd9Sstevel@tonic-gate /* copy global defaults to the new session handle */ 5587c478bd9Sstevel@tonic-gate prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate return( prsessp ); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate static void 5667c478bd9Sstevel@tonic-gate prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ) 5677c478bd9Sstevel@tonic-gate { 5687c478bd9Sstevel@tonic-gate if ( NULL != prsesspp && NULL != *prsesspp ) { 5697c478bd9Sstevel@tonic-gate if ( NULL != (*prsesspp)->prsess_pollds ) { 5707c478bd9Sstevel@tonic-gate PR_Free( (*prsesspp)->prsess_pollds ); 5717c478bd9Sstevel@tonic-gate (*prsesspp)->prsess_pollds = NULL; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate PR_Free( *prsesspp ); 5747c478bd9Sstevel@tonic-gate *prsesspp = NULL; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * Given an LDAP session handle, retrieve a session argument. 5817c478bd9Sstevel@tonic-gate * Returns an LDAP error code. 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate int 5847c478bd9Sstevel@tonic-gate prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ) 5857c478bd9Sstevel@tonic-gate { 5867c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate if ( NULL == ld || NULL == sessargpp ) { 5897c478bd9Sstevel@tonic-gate /* XXXmcs: NULL ld's are not supported */ 5907c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); 5917c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR ); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns)); 5957c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; 5967c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { 5977c478bd9Sstevel@tonic-gate return( ldap_get_lderrno( ld, NULL, NULL )); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if ( NULL == iofns.lextiof_session_arg ) { 6017c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 6027c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate *sessargpp = iofns.lextiof_session_arg; 6067c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS ); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Given an LDAP session handle, retrieve a socket argument. 6127c478bd9Sstevel@tonic-gate * Returns an LDAP error code. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate int 6157c478bd9Sstevel@tonic-gate prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate Sockbuf *sbp; 6187c478bd9Sstevel@tonic-gate struct lber_x_ext_io_fns extiofns; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if ( NULL == ld || NULL == sockargpp ) { 6217c478bd9Sstevel@tonic-gate /* XXXmcs: NULL ld's are not supported */ 6227c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); 6237c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR ); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) { 6277c478bd9Sstevel@tonic-gate return( ldap_get_lderrno( ld, NULL, NULL )); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate memset( &extiofns, 0, sizeof(extiofns)); 6317c478bd9Sstevel@tonic-gate extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; 6327c478bd9Sstevel@tonic-gate if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, 6337c478bd9Sstevel@tonic-gate (void *)&extiofns ) < 0 ) { 6347c478bd9Sstevel@tonic-gate return( ldap_get_lderrno( ld, NULL, NULL )); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if ( NULL == extiofns.lbextiofn_socket_arg ) { 6387c478bd9Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 6397c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate *sockargpp = extiofns.lbextiofn_socket_arg; 6437c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS ); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate /* 6487c478bd9Sstevel@tonic-gate * Allocate a socket argument. 6497c478bd9Sstevel@tonic-gate */ 6507c478bd9Sstevel@tonic-gate static PRLDAPIOSocketArg * 6517c478bd9Sstevel@tonic-gate prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ) 6527c478bd9Sstevel@tonic-gate { 6537c478bd9Sstevel@tonic-gate PRLDAPIOSocketArg *prsockp; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg )); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if ( NULL != prsockp && NULL != sessionarg ) { 6587c478bd9Sstevel@tonic-gate /* copy socket defaults from the session */ 6597c478bd9Sstevel@tonic-gate prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout; 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate return( prsockp ); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate static void 6677c478bd9Sstevel@tonic-gate prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate if ( NULL != prsockpp && NULL != *prsockpp ) { 6707c478bd9Sstevel@tonic-gate PR_Free( *prsockpp ); 6717c478bd9Sstevel@tonic-gate *prsockpp = NULL; 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate static void * 6777c478bd9Sstevel@tonic-gate prldap_safe_realloc( void *ptr, PRUint32 size ) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate void *p; 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate if ( NULL == ptr ) { 6827c478bd9Sstevel@tonic-gate p = PR_Malloc( size ); 6837c478bd9Sstevel@tonic-gate } else { 6847c478bd9Sstevel@tonic-gate p = PR_Realloc( ptr, size ); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate return( p ); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate /* returns an LDAP result code */ 6937c478bd9Sstevel@tonic-gate int 6947c478bd9Sstevel@tonic-gate prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout ) 6957c478bd9Sstevel@tonic-gate { 6967c478bd9Sstevel@tonic-gate int rc = LDAP_SUCCESS; /* optimistic */ 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if ( NULL == prsessp ) { 6997c478bd9Sstevel@tonic-gate prldap_default_io_max_timeout = io_max_timeout; 7007c478bd9Sstevel@tonic-gate } else { 7017c478bd9Sstevel@tonic-gate prsessp->prsess_io_max_timeout = io_max_timeout; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate return( rc ); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* returns an LDAP result code */ 7097c478bd9Sstevel@tonic-gate int 7107c478bd9Sstevel@tonic-gate prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp ) 7117c478bd9Sstevel@tonic-gate { 7127c478bd9Sstevel@tonic-gate int rc = LDAP_SUCCESS; /* optimistic */ 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate if ( NULL == io_max_timeoutp ) { 7157c478bd9Sstevel@tonic-gate rc = LDAP_PARAM_ERROR; 7167c478bd9Sstevel@tonic-gate } else if ( NULL == prsessp ) { 7177c478bd9Sstevel@tonic-gate *io_max_timeoutp = prldap_default_io_max_timeout; 7187c478bd9Sstevel@tonic-gate } else { 7197c478bd9Sstevel@tonic-gate *io_max_timeoutp = prsessp->prsess_io_max_timeout; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate return( rc ); 7237c478bd9Sstevel@tonic-gate } 724