xref: /onnv-gate/usr/src/lib/libldap5/sources/ldap/prldap/ldappr-threads.c (revision 6571:87a1002a7f3b)
10Sstevel@tonic-gate /*
26247Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate 
80Sstevel@tonic-gate 
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
110Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
120Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
130Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
160Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
170Sstevel@tonic-gate  * implied. See the License for the specific language governing
180Sstevel@tonic-gate  * rights and limitations under the License.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
210Sstevel@tonic-gate  * March 31, 1998.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
240Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
250Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
260Sstevel@tonic-gate  * Rights Reserved.
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * Contributor(s):
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * Thread callback functions for libldap that use the NSPR (Netscape
330Sstevel@tonic-gate  * Portable Runtime) thread API.
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #ifdef _SOLARIS_SDK
380Sstevel@tonic-gate #include <thread.h>
390Sstevel@tonic-gate #include <synch.h>
400Sstevel@tonic-gate #include <prinit.h>
410Sstevel@tonic-gate #include <prthread.h>
420Sstevel@tonic-gate #include <syslog.h>
430Sstevel@tonic-gate #include <string.h>
440Sstevel@tonic-gate #include <sys/types.h>
450Sstevel@tonic-gate #include <signal.h>
460Sstevel@tonic-gate #include <errno.h>
470Sstevel@tonic-gate extern int	errno;
480Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #include "ldappr-int.h"
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #ifndef _SOLARIS_SDK
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  * Macros:
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate  * Grow thread private data arrays 10 elements at a time.
580Sstevel@tonic-gate  */
590Sstevel@tonic-gate #define PRLDAP_TPD_ARRAY_INCREMENT	10
600Sstevel@tonic-gate 
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate  * Structures and types:
630Sstevel@tonic-gate  */
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate  * Structure used by libldap thread callbacks to maintain error information.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate typedef struct prldap_errorinfo {
680Sstevel@tonic-gate     int		plei_lderrno;
690Sstevel@tonic-gate     char	*plei_matched;
700Sstevel@tonic-gate     char	*plei_errmsg;
710Sstevel@tonic-gate } PRLDAP_ErrorInfo;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate  * Structure used to maintain thread-private data. At the present time,
750Sstevel@tonic-gate  * only error info. is thread-private.  One of these structures is allocated
760Sstevel@tonic-gate  * for each thread.
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate typedef struct prldap_tpd_header {
790Sstevel@tonic-gate     int			ptpdh_tpd_count;	/* # of data items allocated */
800Sstevel@tonic-gate     void		**ptpdh_dataitems;	/* array of data items */
810Sstevel@tonic-gate } PRLDAP_TPDHeader;
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * Structure used by associate a PRLDAP thread-private data index with an
850Sstevel@tonic-gate  * LDAP session handle. One of these exists for each active LDAP session
860Sstevel@tonic-gate  * handle.
870Sstevel@tonic-gate  */
880Sstevel@tonic-gate typedef struct prldap_tpd_map {
890Sstevel@tonic-gate     LDAP			*prtm_ld;	/* non-NULL if in use */
900Sstevel@tonic-gate     PRUintn			prtm_index;	/* index into TPD array */
910Sstevel@tonic-gate     struct prldap_tpd_map	*prtm_next;
920Sstevel@tonic-gate } PRLDAP_TPDMap;
930Sstevel@tonic-gate 
940Sstevel@tonic-gate #ifdef _SOLARIS_SDK
950Sstevel@tonic-gate extern  mutex_t         inited_mutex;
960Sstevel@tonic-gate #endif  /* _SOLARIS_SDK */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate  * Static Variables:
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * prldap_map_list points to all of the PRLDAP_TPDMap structures
1030Sstevel@tonic-gate  * we have ever allocated.  We recycle them as we open and close LDAP
1040Sstevel@tonic-gate  * sessions.
1050Sstevel@tonic-gate  */
1060Sstevel@tonic-gate static PRLDAP_TPDMap *prldap_map_list = NULL;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate  * The prldap_map_mutex is used to protect access to the prldap_map_list.
1110Sstevel@tonic-gate  */
1120Sstevel@tonic-gate static PRLock	*prldap_map_mutex = NULL;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate  * The prldap_tpd_maxindex value is used to track the largest TPD array
1160Sstevel@tonic-gate  * index we have used.
1170Sstevel@tonic-gate  */
1180Sstevel@tonic-gate static PRInt32	prldap_tpd_maxindex = -1;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate  * prldap_tpdindex is an NSPR thread private data index we use to
1220Sstevel@tonic-gate  * maintain our own thread-private data. It is initialized inside
1230Sstevel@tonic-gate  * prldap_init_tpd().
1240Sstevel@tonic-gate  */
1250Sstevel@tonic-gate static PRUintn	prldap_tpdindex = 0;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate /*
1280Sstevel@tonic-gate  * The prldap_callonce_init_tpd structure is used by NSPR to ensure
1290Sstevel@tonic-gate  * that prldap_init_tpd() is called at most once.
1300Sstevel@tonic-gate  */
1310Sstevel@tonic-gate static PRCallOnceType prldap_callonce_init_tpd = { 0, 0, 0 };
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate  * Private function prototypes:
1360Sstevel@tonic-gate  */
1370Sstevel@tonic-gate static void prldap_set_ld_error( int err, char *matched, char *errmsg,
1380Sstevel@tonic-gate 	void *errorarg );
1390Sstevel@tonic-gate static int prldap_get_ld_error( char **matchedp, char **errmsgp,
1400Sstevel@tonic-gate 	void *errorarg );
1410Sstevel@tonic-gate #endif
1420Sstevel@tonic-gate static void *prldap_mutex_alloc( void );
1430Sstevel@tonic-gate static void prldap_mutex_free( void *mutex );
1440Sstevel@tonic-gate static int prldap_mutex_lock( void *mutex );
1450Sstevel@tonic-gate static int prldap_mutex_unlock( void *mutex );
1460Sstevel@tonic-gate static void *prldap_get_thread_id( void );
1470Sstevel@tonic-gate #ifndef _SOLARIS_SDK
1480Sstevel@tonic-gate static PRStatus prldap_init_tpd( void );
1490Sstevel@tonic-gate static PRLDAP_TPDMap *prldap_allocate_map( LDAP *ld );
1500Sstevel@tonic-gate static void prldap_return_map( PRLDAP_TPDMap *map );
1510Sstevel@tonic-gate static PRUintn prldap_new_tpdindex( void );
1520Sstevel@tonic-gate static int prldap_set_thread_private( PRInt32 tpdindex, void *priv );
1530Sstevel@tonic-gate static void *prldap_get_thread_private( PRInt32 tpdindex );
1540Sstevel@tonic-gate static PRLDAP_TPDHeader *prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr,
1550Sstevel@tonic-gate 	int maxindex );
1560Sstevel@tonic-gate static void prldap_tsd_destroy( void *priv );
1570Sstevel@tonic-gate #endif
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate  * Install NSPR thread functions into ld (if ld is NULL, they are installed
1620Sstevel@tonic-gate  * as the default functions for new LDAP * handles).
1630Sstevel@tonic-gate  *
1640Sstevel@tonic-gate  * Returns 0 if all goes well and -1 if not.
1650Sstevel@tonic-gate  */
1660Sstevel@tonic-gate int
prldap_install_thread_functions(LDAP * ld,int shared)1670Sstevel@tonic-gate prldap_install_thread_functions( LDAP *ld, int shared )
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate     struct ldap_thread_fns		tfns;
1700Sstevel@tonic-gate     struct ldap_extra_thread_fns	xtfns;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate #ifndef _SOLARIS_SDK
1730Sstevel@tonic-gate     if ( PR_CallOnce( &prldap_callonce_init_tpd, prldap_init_tpd )
1740Sstevel@tonic-gate 		!= PR_SUCCESS ) {
1750Sstevel@tonic-gate 	ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
1760Sstevel@tonic-gate 	return( -1 );
1770Sstevel@tonic-gate     }
1780Sstevel@tonic-gate #endif	/* _SOLARIS_SDK */
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate     /* set thread function pointers */
1810Sstevel@tonic-gate     memset( &tfns, '\0', sizeof(struct ldap_thread_fns) );
1820Sstevel@tonic-gate     tfns.ltf_get_errno = prldap_get_system_errno;
1830Sstevel@tonic-gate     tfns.ltf_set_errno = prldap_set_system_errno;
1840Sstevel@tonic-gate     if ( shared ) {
1850Sstevel@tonic-gate 	tfns.ltf_mutex_alloc = prldap_mutex_alloc;
1860Sstevel@tonic-gate 	tfns.ltf_mutex_free = prldap_mutex_free;
1870Sstevel@tonic-gate 	tfns.ltf_mutex_lock = prldap_mutex_lock;
1880Sstevel@tonic-gate 	tfns.ltf_mutex_unlock = prldap_mutex_unlock;
1890Sstevel@tonic-gate #ifdef _SOLARIS_SDK
1900Sstevel@tonic-gate 	tfns.ltf_get_lderrno = NULL;
1910Sstevel@tonic-gate 	tfns.ltf_set_lderrno = NULL;
1920Sstevel@tonic-gate #else
1930Sstevel@tonic-gate 	tfns.ltf_get_lderrno = prldap_get_ld_error;
1940Sstevel@tonic-gate 	tfns.ltf_set_lderrno = prldap_set_ld_error;
1950Sstevel@tonic-gate 	if ( ld != NULL ) {
1960Sstevel@tonic-gate 	    /*
1970Sstevel@tonic-gate 	     * If this is a real ld (i.e., we are not setting the global
1980Sstevel@tonic-gate 	     * defaults) allocate thread private data for error information.
1990Sstevel@tonic-gate 	     * If ld is NULL we do not do this here but it is done in
2000Sstevel@tonic-gate 	     * prldap_thread_new_handle().
2010Sstevel@tonic-gate 	     */
2020Sstevel@tonic-gate 	    if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld ))
2030Sstevel@tonic-gate 		    == NULL ) {
2040Sstevel@tonic-gate 		return( -1 );
2050Sstevel@tonic-gate 	    }
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate #endif
2080Sstevel@tonic-gate     }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS,
2110Sstevel@tonic-gate 	    (void *)&tfns ) != 0 ) {
2120Sstevel@tonic-gate #ifndef _SOLARIS_SDK
2130Sstevel@tonic-gate 	prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg );
2140Sstevel@tonic-gate #endif
2150Sstevel@tonic-gate 	return( -1 );
2160Sstevel@tonic-gate     }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate     /* set extended thread function pointers */
2190Sstevel@tonic-gate     memset( &xtfns, '\0', sizeof(struct ldap_extra_thread_fns) );
2200Sstevel@tonic-gate     xtfns.ltf_threadid_fn = prldap_get_thread_id;
2210Sstevel@tonic-gate     if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS,
2220Sstevel@tonic-gate 	    (void *)&xtfns ) != 0 ) {
2230Sstevel@tonic-gate 	return( -1 );
2240Sstevel@tonic-gate     }
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate     return( 0 );
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate static void *
prldap_mutex_alloc(void)2310Sstevel@tonic-gate prldap_mutex_alloc( void )
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate     return( (void *)PR_NewLock());
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate static void
prldap_mutex_free(void * mutex)2380Sstevel@tonic-gate prldap_mutex_free( void *mutex )
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate     PR_DestroyLock( (PRLock *)mutex );
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate static int
prldap_mutex_lock(void * mutex)2450Sstevel@tonic-gate prldap_mutex_lock( void *mutex )
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate     PR_Lock( (PRLock *)mutex );
2480Sstevel@tonic-gate     return( 0 );
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate static int
prldap_mutex_unlock(void * mutex)2530Sstevel@tonic-gate prldap_mutex_unlock( void *mutex )
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate     if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) {
2560Sstevel@tonic-gate 	return( -1 );
2570Sstevel@tonic-gate     }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate     return( 0 );
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate static void *
prldap_get_thread_id(void)2640Sstevel@tonic-gate prldap_get_thread_id( void )
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate #ifdef	_SOLARIS_SDK
2670Sstevel@tonic-gate 	return ((void *)thr_self());
2680Sstevel@tonic-gate #else
2690Sstevel@tonic-gate     return( (void *)PR_GetCurrentThread());
2700Sstevel@tonic-gate #endif
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate #ifndef	_SOLARIS_SDK
2740Sstevel@tonic-gate static int
prldap_get_ld_error(char ** matchedp,char ** errmsgp,void * errorarg)2750Sstevel@tonic-gate prldap_get_ld_error( char **matchedp, char **errmsgp, void *errorarg )
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate     PRLDAP_TPDMap	*map;
2780Sstevel@tonic-gate     PRLDAP_ErrorInfo	*eip;
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate     if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL && ( eip =
2810Sstevel@tonic-gate 	    (PRLDAP_ErrorInfo *)prldap_get_thread_private(
2820Sstevel@tonic-gate 	    map->prtm_index )) != NULL ) {
2830Sstevel@tonic-gate 	if ( matchedp != NULL ) {
2840Sstevel@tonic-gate 	    *matchedp = eip->plei_matched;
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 	if ( errmsgp != NULL ) {
2870Sstevel@tonic-gate 	    *errmsgp = eip->plei_errmsg;
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 	return( eip->plei_lderrno );
2900Sstevel@tonic-gate     } else {
2910Sstevel@tonic-gate 	if ( matchedp != NULL ) {
2920Sstevel@tonic-gate 	    *matchedp = NULL;
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 	if ( errmsgp != NULL ) {
2950Sstevel@tonic-gate 	    *errmsgp = NULL;
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	return( LDAP_LOCAL_ERROR );	/* punt */
2980Sstevel@tonic-gate     }
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate static void
prldap_set_ld_error(int err,char * matched,char * errmsg,void * errorarg)3030Sstevel@tonic-gate prldap_set_ld_error( int err, char *matched, char *errmsg, void *errorarg )
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate     PRLDAP_TPDMap	*map;
3060Sstevel@tonic-gate     PRLDAP_ErrorInfo	*eip;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate     if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL ) {
3090Sstevel@tonic-gate 	if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private(
3100Sstevel@tonic-gate 		map->prtm_index )) == NULL ) {
3110Sstevel@tonic-gate 	    /*
3120Sstevel@tonic-gate 	     * Error info. has not yet been allocated for this thread.
3130Sstevel@tonic-gate 	     * Do so now.  Note that we free this memory only for the
3140Sstevel@tonic-gate 	     * thread that calls prldap_thread_dispose_handle(), which
3150Sstevel@tonic-gate 	     * should be the one that called ldap_unbind() -- see
3160Sstevel@tonic-gate 	     * prldap_return_map().  Not freeing the memory used by
3170Sstevel@tonic-gate 	     * other threads is deemed acceptable since it will be
3180Sstevel@tonic-gate 	     * recycled and used by other LDAP sessions.  All of the
3190Sstevel@tonic-gate 	     * thread-private memory is freed when a thread exits
3200Sstevel@tonic-gate 	     * (inside the prldap_tsd_destroy() function).
3210Sstevel@tonic-gate 	     */
3220Sstevel@tonic-gate 	    eip = (PRLDAP_ErrorInfo *)PR_Calloc( 1,
3230Sstevel@tonic-gate 		    sizeof( PRLDAP_ErrorInfo ));
3240Sstevel@tonic-gate 	    if ( eip == NULL ) {
3250Sstevel@tonic-gate 		return;	/* punt */
3260Sstevel@tonic-gate 	    }
3270Sstevel@tonic-gate 	    (void)prldap_set_thread_private( map->prtm_index, eip );
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	eip->plei_lderrno = err;
3310Sstevel@tonic-gate 	if ( eip->plei_matched != NULL ) {
3320Sstevel@tonic-gate 	    ldap_memfree( eip->plei_matched );
3330Sstevel@tonic-gate 	}
3340Sstevel@tonic-gate 	eip->plei_matched = matched;
3350Sstevel@tonic-gate 	if ( eip->plei_errmsg != NULL ) {
3360Sstevel@tonic-gate 	    ldap_memfree( eip->plei_errmsg );
3370Sstevel@tonic-gate 	}
3380Sstevel@tonic-gate 	eip->plei_errmsg = errmsg;
3390Sstevel@tonic-gate     }
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate #endif
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  * Called when a new LDAP * session handle is allocated.
3460Sstevel@tonic-gate  * Allocate thread-private data for error information, but only if
3470Sstevel@tonic-gate  * it has not already been allocated and the get_ld_error callback has
3480Sstevel@tonic-gate  * been installed.  If ld is not NULL when prldap_install_thread_functions()
3490Sstevel@tonic-gate  * is called, we will have already allocated the thread-private data there.
3500Sstevel@tonic-gate  */
3510Sstevel@tonic-gate int
prldap_thread_new_handle(LDAP * ld,void * sessionarg)3520Sstevel@tonic-gate prldap_thread_new_handle( LDAP *ld, void *sessionarg )
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate     struct ldap_thread_fns	tfns;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate #ifndef _SOLARIS_SDK
3570Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *)&tfns ) != 0 ) {
3580Sstevel@tonic-gate 	return( LDAP_LOCAL_ERROR );
3590Sstevel@tonic-gate     }
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate     if ( tfns.ltf_lderrno_arg == NULL && tfns.ltf_get_lderrno != NULL ) {
3620Sstevel@tonic-gate 	if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) == NULL
3630Sstevel@tonic-gate 		|| ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS,
3640Sstevel@tonic-gate 		(void *)&tfns ) != 0 ) {
3650Sstevel@tonic-gate 	    return( LDAP_LOCAL_ERROR );
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate     }
3680Sstevel@tonic-gate #endif
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate     return( LDAP_SUCCESS );
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate  * Called when an LDAP * session handle is being destroyed.
3760Sstevel@tonic-gate  * Clean up our thread private data map.
3770Sstevel@tonic-gate  */
3780Sstevel@tonic-gate void
prldap_thread_dispose_handle(LDAP * ld,void * sessionarg)3790Sstevel@tonic-gate prldap_thread_dispose_handle( LDAP *ld, void *sessionarg )
3800Sstevel@tonic-gate {
3810Sstevel@tonic-gate #ifndef _SOLARIS_SDK
3820Sstevel@tonic-gate     struct ldap_thread_fns	tfns;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate     if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS,
3850Sstevel@tonic-gate 	    (void *)&tfns ) == 0 &&
3860Sstevel@tonic-gate 	    tfns.ltf_lderrno_arg != NULL ) {
3870Sstevel@tonic-gate 	prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg );
3880Sstevel@tonic-gate     }
3890Sstevel@tonic-gate #endif
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate #ifndef _SOLARIS_SDK
3940Sstevel@tonic-gate static PRStatus
prldap_init_tpd(void)3950Sstevel@tonic-gate prldap_init_tpd( void )
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate     if (( prldap_map_mutex = PR_NewLock()) == NULL || PR_NewThreadPrivateIndex(
3980Sstevel@tonic-gate 		&prldap_tpdindex, prldap_tsd_destroy ) != PR_SUCCESS ) {
3990Sstevel@tonic-gate 	return( PR_FAILURE );
4000Sstevel@tonic-gate     }
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate     prldap_map_list = NULL;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate     return( PR_SUCCESS );
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate  * Function: prldap_allocate_map()
4100Sstevel@tonic-gate  * Description: allocate a thread-private data map to use for a new
4110Sstevel@tonic-gate  *	LDAP session handle.
4120Sstevel@tonic-gate  * Returns: a pointer to the TPD map or NULL if none available.
4130Sstevel@tonic-gate  */
4140Sstevel@tonic-gate static PRLDAP_TPDMap *
prldap_allocate_map(LDAP * ld)4150Sstevel@tonic-gate prldap_allocate_map( LDAP *ld )
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate     PRLDAP_TPDMap	*map, *prevmap;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate     PR_Lock( prldap_map_mutex );
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate     /*
4220Sstevel@tonic-gate      * first look for a map that is already allocated but free to be re-used
4230Sstevel@tonic-gate      */
4240Sstevel@tonic-gate     prevmap = NULL;
4250Sstevel@tonic-gate     for ( map = prldap_map_list; map != NULL; map = map->prtm_next ) {
4260Sstevel@tonic-gate 	if ( map->prtm_ld == NULL ) {
4270Sstevel@tonic-gate 	    break;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 	prevmap = map;
4300Sstevel@tonic-gate     }
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate     /*
4330Sstevel@tonic-gate      * if none we found (map == NULL), try to allocate a new one and add it
4340Sstevel@tonic-gate      * to the end of our global list.
4350Sstevel@tonic-gate      */
4360Sstevel@tonic-gate     if ( map == NULL ) {
4370Sstevel@tonic-gate 	PRUintn	tpdindex;
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	tpdindex = prldap_new_tpdindex();
4400Sstevel@tonic-gate 	map = (PRLDAP_TPDMap *)PR_Malloc( sizeof( PRLDAP_TPDMap ));
4410Sstevel@tonic-gate 	if ( map != NULL ) {
4420Sstevel@tonic-gate 	    map->prtm_index = tpdindex;
4430Sstevel@tonic-gate 	    map->prtm_next = NULL;
4440Sstevel@tonic-gate 	    if ( prevmap == NULL ) {
4450Sstevel@tonic-gate 		prldap_map_list = map;
4460Sstevel@tonic-gate 	    } else {
4470Sstevel@tonic-gate 		prevmap->prtm_next = map;
4480Sstevel@tonic-gate 	    }
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate     }
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate     if ( map != NULL ) {
4530Sstevel@tonic-gate 	map->prtm_ld = ld;	/* now marked as "in use" */
4540Sstevel@tonic-gate 				/* since we are reusing...reset */
4550Sstevel@tonic-gate 				/* to initial state */
4560Sstevel@tonic-gate 	(void)prldap_set_thread_private( map->prtm_index, NULL );
4570Sstevel@tonic-gate     }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate     PR_Unlock( prldap_map_mutex );
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate     return( map );
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate /*
4660Sstevel@tonic-gate  * Function: prldap_return_map()
4670Sstevel@tonic-gate  * Description: return a thread-private data map to the pool of ones
4680Sstevel@tonic-gate  *	available for re-use.
4690Sstevel@tonic-gate  */
4700Sstevel@tonic-gate static void
prldap_return_map(PRLDAP_TPDMap * map)4710Sstevel@tonic-gate prldap_return_map( PRLDAP_TPDMap *map )
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate     PRLDAP_ErrorInfo	*eip;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate     PR_Lock( prldap_map_mutex );
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate     /*
4780Sstevel@tonic-gate      * Dispose of thread-private LDAP error information.  Note that this
4790Sstevel@tonic-gate      * only disposes of the memory consumed on THIS thread, but that is
4800Sstevel@tonic-gate      * okay.  See the comment in prldap_set_ld_error() for the reason why.
4810Sstevel@tonic-gate      */
4820Sstevel@tonic-gate     if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private(
4830Sstevel@tonic-gate 		map->prtm_index )) != NULL &&
4840Sstevel@tonic-gate 		prldap_set_thread_private( map->prtm_index, NULL ) == 0 ) {
4850Sstevel@tonic-gate 	if ( eip->plei_matched != NULL ) {
4860Sstevel@tonic-gate 	    ldap_memfree( eip->plei_matched );
4870Sstevel@tonic-gate 	}
4880Sstevel@tonic-gate 	if ( eip->plei_errmsg != NULL ) {
4890Sstevel@tonic-gate 	    ldap_memfree( eip->plei_errmsg );
4900Sstevel@tonic-gate 	}
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	PR_Free( eip );
4930Sstevel@tonic-gate     }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate     /* mark map as available for re-use */
4960Sstevel@tonic-gate     map->prtm_ld = NULL;
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate     PR_Unlock( prldap_map_mutex );
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate /*
5030Sstevel@tonic-gate  * Function: prldap_new_tpdindex()
5040Sstevel@tonic-gate  * Description: allocate a thread-private data index.
5050Sstevel@tonic-gate  * Returns: the new index.
5060Sstevel@tonic-gate  */
5070Sstevel@tonic-gate static PRUintn
prldap_new_tpdindex(void)5080Sstevel@tonic-gate prldap_new_tpdindex( void )
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate     PRUintn	tpdindex;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate     tpdindex = (PRUintn)PR_AtomicIncrement( &prldap_tpd_maxindex );
5130Sstevel@tonic-gate     return( tpdindex );
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate /*
5180Sstevel@tonic-gate  * Function: prldap_set_thread_private()
5190Sstevel@tonic-gate  * Description: store a piece of thread-private data.
5200Sstevel@tonic-gate  * Returns: 0 if successful and -1 if not.
5210Sstevel@tonic-gate  */
5220Sstevel@tonic-gate static int
prldap_set_thread_private(PRInt32 tpdindex,void * priv)5230Sstevel@tonic-gate prldap_set_thread_private( PRInt32 tpdindex, void *priv )
5240Sstevel@tonic-gate {
5250Sstevel@tonic-gate     PRLDAP_TPDHeader	*tsdhdr;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate     if ( tpdindex > prldap_tpd_maxindex ) {
5280Sstevel@tonic-gate 	return( -1 );	/* bad index */
5290Sstevel@tonic-gate     }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate     tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex );
5320Sstevel@tonic-gate     if ( tsdhdr == NULL || tpdindex >= tsdhdr->ptpdh_tpd_count ) {
5330Sstevel@tonic-gate 	tsdhdr = prldap_tsd_realloc( tsdhdr, tpdindex );
5340Sstevel@tonic-gate 	if ( tsdhdr == NULL ) {
5350Sstevel@tonic-gate 	    return( -1 );	/* realloc failed */
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate     }
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate     tsdhdr->ptpdh_dataitems[ tpdindex ] = priv;
5400Sstevel@tonic-gate     return( 0 );
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate  * Function: prldap_get_thread_private()
5460Sstevel@tonic-gate  * Description: retrieve a piece of thread-private data.  If not set,
5470Sstevel@tonic-gate  *	NULL is returned.
5480Sstevel@tonic-gate  * Returns: 0 if successful and -1 if not.
5490Sstevel@tonic-gate  */
5500Sstevel@tonic-gate static void *
prldap_get_thread_private(PRInt32 tpdindex)5510Sstevel@tonic-gate prldap_get_thread_private( PRInt32 tpdindex )
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate     PRLDAP_TPDHeader	*tsdhdr;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate     tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex );
5560Sstevel@tonic-gate     if ( tsdhdr == NULL ) {
5570Sstevel@tonic-gate 	return( NULL );	/* no thread private data */
5580Sstevel@tonic-gate     }
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate     if ( tpdindex >= tsdhdr->ptpdh_tpd_count
5610Sstevel@tonic-gate 		|| tsdhdr->ptpdh_dataitems == NULL ) {
5620Sstevel@tonic-gate 	return( NULL );	/* fewer data items than requested index */
5630Sstevel@tonic-gate     }
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate     return( tsdhdr->ptpdh_dataitems[ tpdindex ] );
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate  * Function: prldap_tsd_realloc()
5710Sstevel@tonic-gate  * Description: enlarge the thread-private data array.
5720Sstevel@tonic-gate  * Returns: the new PRLDAP_TPDHeader value (non-NULL if successful).
5730Sstevel@tonic-gate  * Note: tsdhdr can be NULL (allocates a new PRLDAP_TPDHeader).
5740Sstevel@tonic-gate  */
5750Sstevel@tonic-gate static PRLDAP_TPDHeader *
prldap_tsd_realloc(PRLDAP_TPDHeader * tsdhdr,int maxindex)5760Sstevel@tonic-gate prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, int maxindex )
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate     void	*newdataitems = NULL;
5790Sstevel@tonic-gate     int		count;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate     if ( tsdhdr == NULL ) {
5820Sstevel@tonic-gate 	/* allocate a new thread private data header */
5830Sstevel@tonic-gate 	if (( tsdhdr = PR_Calloc( 1, sizeof( PRLDAP_TPDHeader ))) == NULL ) {
5840Sstevel@tonic-gate 	    return( NULL );
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 	(void)PR_SetThreadPrivate( prldap_tpdindex, tsdhdr );
5870Sstevel@tonic-gate     }
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate     /*
5900Sstevel@tonic-gate      * Make the size of the new array the next highest multiple of
5910Sstevel@tonic-gate      * the array increment value that is greater than maxindex.
5920Sstevel@tonic-gate      */
5930Sstevel@tonic-gate     count = PRLDAP_TPD_ARRAY_INCREMENT *
5940Sstevel@tonic-gate 		( 1 + ( maxindex / PRLDAP_TPD_ARRAY_INCREMENT ));
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate     /* increase the size of the data item array if necessary */
5970Sstevel@tonic-gate     if ( count > tsdhdr->ptpdh_tpd_count  ) {
5980Sstevel@tonic-gate 	newdataitems = (PRLDAP_ErrorInfo *)PR_Calloc( count, sizeof( void * ));
5990Sstevel@tonic-gate 	if ( newdataitems == NULL ) {
6000Sstevel@tonic-gate 	    return( NULL );
6010Sstevel@tonic-gate 	}
6020Sstevel@tonic-gate 	if ( tsdhdr->ptpdh_dataitems != NULL ) {	/* preserve old data */
6030Sstevel@tonic-gate 	    memcpy( newdataitems, tsdhdr->ptpdh_dataitems,
6040Sstevel@tonic-gate 			tsdhdr->ptpdh_tpd_count * sizeof( void * ));
6050Sstevel@tonic-gate 	    PR_Free( tsdhdr->ptpdh_dataitems );
6060Sstevel@tonic-gate 	}
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	tsdhdr->ptpdh_tpd_count = count;
6090Sstevel@tonic-gate 	tsdhdr->ptpdh_dataitems = newdataitems;
6100Sstevel@tonic-gate     }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate     return( tsdhdr );
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate  * Function: prldap_tsd_destroy()
6180Sstevel@tonic-gate  * Description: Free a thread-private data array. Installed as an NSPR TPD
6190Sstevel@tonic-gate  *	destructor function
6200Sstevel@tonic-gate  * Returns: nothing.
6210Sstevel@tonic-gate  * Note: this function assumes that each TPD item installed at the PRLDAP
6220Sstevel@tonic-gate  *	level can be freed with a call to PR_Free().
6230Sstevel@tonic-gate  */
6240Sstevel@tonic-gate static void
prldap_tsd_destroy(void * priv)6250Sstevel@tonic-gate prldap_tsd_destroy( void *priv )
6260Sstevel@tonic-gate {
6270Sstevel@tonic-gate     PRLDAP_TPDHeader	*tsdhdr;
6280Sstevel@tonic-gate     int			i;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate     tsdhdr = (PRLDAP_TPDHeader *)priv;
6310Sstevel@tonic-gate     if ( tsdhdr != NULL ) {
6320Sstevel@tonic-gate 	if ( tsdhdr->ptpdh_dataitems != NULL ) {
6330Sstevel@tonic-gate 	    for ( i = 0; i < tsdhdr->ptpdh_tpd_count; ++i ) {
6340Sstevel@tonic-gate 		if ( tsdhdr->ptpdh_dataitems[ i ] != NULL ) {
6350Sstevel@tonic-gate 		    PR_Free( tsdhdr->ptpdh_dataitems[ i ] );
6360Sstevel@tonic-gate 		    tsdhdr->ptpdh_dataitems[ i ] = NULL;
6370Sstevel@tonic-gate 		}
6380Sstevel@tonic-gate 	    }
6390Sstevel@tonic-gate 	    PR_Free( tsdhdr->ptpdh_dataitems );
6400Sstevel@tonic-gate 	    tsdhdr->ptpdh_dataitems = NULL;
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate 	PR_Free( tsdhdr );
6430Sstevel@tonic-gate     }
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate #endif
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate #ifdef	_SOLARIS_SDK
6480Sstevel@tonic-gate #pragma	init(prldap_nspr_init)
6490Sstevel@tonic-gate static mutex_t	nspr_init_lock = DEFAULTMUTEX;
6500Sstevel@tonic-gate static int	nspr_initialized = 0;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate /*
6530Sstevel@tonic-gate  * Initialize NSPR once
6540Sstevel@tonic-gate  *
6550Sstevel@tonic-gate  */
6560Sstevel@tonic-gate void
prldap_nspr_init(void)6570Sstevel@tonic-gate prldap_nspr_init(void) {
6580Sstevel@tonic-gate 	struct sigaction	action;
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	/*
6610Sstevel@tonic-gate 	 * For performance reason, test it here first
6620Sstevel@tonic-gate 	 */
6630Sstevel@tonic-gate 	if (nspr_initialized != 0)
6640Sstevel@tonic-gate 		return;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	(void) mutex_lock(&nspr_init_lock);
6670Sstevel@tonic-gate 	/* Make sure PR_Init() is executed only once */
6680Sstevel@tonic-gate 	if (nspr_initialized == 0) {
6690Sstevel@tonic-gate 		/*
6700Sstevel@tonic-gate 		 * PR_Init changes the signal handler of SIGPIPE to SIG_IGN.
6710Sstevel@tonic-gate 		 * Save the original and restore it after PR_Init.
6720Sstevel@tonic-gate 		 */
6730Sstevel@tonic-gate 		(void) sigaction(SIGPIPE, NULL, &action);
6740Sstevel@tonic-gate 
675*6571Sth160488 		if (PR_Initialized() == PR_FALSE) {
6760Sstevel@tonic-gate 			/*
677*6571Sth160488 			 * PR_Init() changes the current thread's
678*6571Sth160488 			 * priority.  Save and restore the priority.
6790Sstevel@tonic-gate 			 */
680*6571Sth160488 			int priority;
681*6571Sth160488 			(void) thr_getprio(thr_self(), &priority);
682*6571Sth160488 			PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
683*6571Sth160488 			(void) thr_setprio(thr_self(), priority);
6840Sstevel@tonic-gate 		}
685*6571Sth160488 		nspr_initialized = 1;
6860Sstevel@tonic-gate 		/*
6870Sstevel@tonic-gate 		 * Restore signal handling attributes of SIGPIPE
6880Sstevel@tonic-gate 		 */
6890Sstevel@tonic-gate 		(void) sigaction(SIGPIPE, &action, NULL);
6900Sstevel@tonic-gate 	}
6910Sstevel@tonic-gate 	(void) mutex_unlock(&nspr_init_lock);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate #endif
694