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 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 * 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 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 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 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 * 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 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 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 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 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 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 * 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 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 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 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 * 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 * 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 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 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