1*10706SJulian.Pullen@Sun.COM /* 2*10706SJulian.Pullen@Sun.COM * CDDL HEADER START 3*10706SJulian.Pullen@Sun.COM * 4*10706SJulian.Pullen@Sun.COM * The contents of this file are subject to the terms of the 5*10706SJulian.Pullen@Sun.COM * Common Development and Distribution License (the "License"). 6*10706SJulian.Pullen@Sun.COM * You may not use this file except in compliance with the License. 7*10706SJulian.Pullen@Sun.COM * 8*10706SJulian.Pullen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*10706SJulian.Pullen@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*10706SJulian.Pullen@Sun.COM * See the License for the specific language governing permissions 11*10706SJulian.Pullen@Sun.COM * and limitations under the License. 12*10706SJulian.Pullen@Sun.COM * 13*10706SJulian.Pullen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*10706SJulian.Pullen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*10706SJulian.Pullen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*10706SJulian.Pullen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*10706SJulian.Pullen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*10706SJulian.Pullen@Sun.COM * 19*10706SJulian.Pullen@Sun.COM * CDDL HEADER END 20*10706SJulian.Pullen@Sun.COM */ 21*10706SJulian.Pullen@Sun.COM 22*10706SJulian.Pullen@Sun.COM /* 23*10706SJulian.Pullen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*10706SJulian.Pullen@Sun.COM * Use is subject to license terms. 25*10706SJulian.Pullen@Sun.COM */ 26*10706SJulian.Pullen@Sun.COM 27*10706SJulian.Pullen@Sun.COM /* 28*10706SJulian.Pullen@Sun.COM * Functions for managing thread-local storage for LDAP, and in particular 29*10706SJulian.Pullen@Sun.COM * for managing storage of the LDAP error state. 30*10706SJulian.Pullen@Sun.COM */ 31*10706SJulian.Pullen@Sun.COM 32*10706SJulian.Pullen@Sun.COM #include <ldap.h> 33*10706SJulian.Pullen@Sun.COM #include <pthread.h> 34*10706SJulian.Pullen@Sun.COM #include <errno.h> 35*10706SJulian.Pullen@Sun.COM #include <note.h> 36*10706SJulian.Pullen@Sun.COM #include <syslog.h> 37*10706SJulian.Pullen@Sun.COM #include <string.h> 38*10706SJulian.Pullen@Sun.COM #include "solaris-int.h" /* This is a libladp5 private include file */ 39*10706SJulian.Pullen@Sun.COM /* which has the defintion for */ 40*10706SJulian.Pullen@Sun.COM /* struct ldap_extra_thread_fns */ 41*10706SJulian.Pullen@Sun.COM #include "adutils_impl.h" 42*10706SJulian.Pullen@Sun.COM 43*10706SJulian.Pullen@Sun.COM struct adutils_lderrno { 44*10706SJulian.Pullen@Sun.COM int le_errno; 45*10706SJulian.Pullen@Sun.COM char *le_matched; 46*10706SJulian.Pullen@Sun.COM char *le_errmsg; 47*10706SJulian.Pullen@Sun.COM }; 48*10706SJulian.Pullen@Sun.COM 49*10706SJulian.Pullen@Sun.COM static void *adutils_mutex_alloc(void); 50*10706SJulian.Pullen@Sun.COM static void adutils_mutex_free(void *mutexp); 51*10706SJulian.Pullen@Sun.COM static int adutils_get_errno(void); 52*10706SJulian.Pullen@Sun.COM static void adutils_set_errno(int err); 53*10706SJulian.Pullen@Sun.COM static void adutils_set_lderrno(int err, char *matched, char *errmsg, 54*10706SJulian.Pullen@Sun.COM void *dummy); 55*10706SJulian.Pullen@Sun.COM static int adutils_get_lderrno(char **matched, char **errmsg, void *dummy); 56*10706SJulian.Pullen@Sun.COM static void adutils_lderrno_destructor(void *tsd); 57*10706SJulian.Pullen@Sun.COM 58*10706SJulian.Pullen@Sun.COM static pthread_key_t adutils_lderrno_key = PTHREAD_ONCE_KEY_NP; 59*10706SJulian.Pullen@Sun.COM 60*10706SJulian.Pullen@Sun.COM static struct ldap_thread_fns thread_fns = { 61*10706SJulian.Pullen@Sun.COM .ltf_mutex_alloc = adutils_mutex_alloc, 62*10706SJulian.Pullen@Sun.COM .ltf_mutex_free = adutils_mutex_free, 63*10706SJulian.Pullen@Sun.COM .ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock, 64*10706SJulian.Pullen@Sun.COM .ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock, 65*10706SJulian.Pullen@Sun.COM .ltf_get_errno = adutils_get_errno, 66*10706SJulian.Pullen@Sun.COM .ltf_set_errno = adutils_set_errno, 67*10706SJulian.Pullen@Sun.COM .ltf_get_lderrno = adutils_get_lderrno, 68*10706SJulian.Pullen@Sun.COM .ltf_set_lderrno = adutils_set_lderrno, 69*10706SJulian.Pullen@Sun.COM .ltf_lderrno_arg = NULL 70*10706SJulian.Pullen@Sun.COM }; 71*10706SJulian.Pullen@Sun.COM 72*10706SJulian.Pullen@Sun.COM struct ldap_extra_thread_fns extra_thread_fns = { 73*10706SJulian.Pullen@Sun.COM .ltf_threadid_fn = (void * (*)(void))pthread_self 74*10706SJulian.Pullen@Sun.COM }; 75*10706SJulian.Pullen@Sun.COM 76*10706SJulian.Pullen@Sun.COM 77*10706SJulian.Pullen@Sun.COM /* 78*10706SJulian.Pullen@Sun.COM * Set up thread management functions for the specified LDAP session. 79*10706SJulian.Pullen@Sun.COM * Returns either LDAP_SUCCESS or -1. 80*10706SJulian.Pullen@Sun.COM */ 81*10706SJulian.Pullen@Sun.COM int 82*10706SJulian.Pullen@Sun.COM adutils_set_thread_functions(LDAP *ld) 83*10706SJulian.Pullen@Sun.COM { 84*10706SJulian.Pullen@Sun.COM int rc; 85*10706SJulian.Pullen@Sun.COM 86*10706SJulian.Pullen@Sun.COM if (adutils_lderrno_key == PTHREAD_ONCE_KEY_NP) { 87*10706SJulian.Pullen@Sun.COM if ((rc = pthread_key_create_once_np(&adutils_lderrno_key, 88*10706SJulian.Pullen@Sun.COM adutils_lderrno_destructor)) != 0) { 89*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, "adutils_set_thread_functions() " 90*10706SJulian.Pullen@Sun.COM "pthread_key_create_once_np failed (%s)", 91*10706SJulian.Pullen@Sun.COM strerror(rc)); 92*10706SJulian.Pullen@Sun.COM rc = -1; 93*10706SJulian.Pullen@Sun.COM return (rc); 94*10706SJulian.Pullen@Sun.COM } 95*10706SJulian.Pullen@Sun.COM } 96*10706SJulian.Pullen@Sun.COM 97*10706SJulian.Pullen@Sun.COM rc = ldap_set_option(ld, LDAP_OPT_THREAD_FN_PTRS, 98*10706SJulian.Pullen@Sun.COM &thread_fns); 99*10706SJulian.Pullen@Sun.COM if (rc != LDAP_SUCCESS) { 100*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 101*10706SJulian.Pullen@Sun.COM "ldap_set_option LDAP_OPT_THREAD_FN_PTRS failed"); 102*10706SJulian.Pullen@Sun.COM return (rc); 103*10706SJulian.Pullen@Sun.COM } 104*10706SJulian.Pullen@Sun.COM 105*10706SJulian.Pullen@Sun.COM rc = ldap_set_option(ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, 106*10706SJulian.Pullen@Sun.COM &extra_thread_fns); 107*10706SJulian.Pullen@Sun.COM if (rc != LDAP_SUCCESS) { 108*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 109*10706SJulian.Pullen@Sun.COM "ldap_set_option LDAP_OPT_EXTRA_THREAD_FN_PTRS failed"); 110*10706SJulian.Pullen@Sun.COM return (rc); 111*10706SJulian.Pullen@Sun.COM } 112*10706SJulian.Pullen@Sun.COM return (rc); 113*10706SJulian.Pullen@Sun.COM } 114*10706SJulian.Pullen@Sun.COM 115*10706SJulian.Pullen@Sun.COM /* 116*10706SJulian.Pullen@Sun.COM * Allocate a mutex. 117*10706SJulian.Pullen@Sun.COM */ 118*10706SJulian.Pullen@Sun.COM static 119*10706SJulian.Pullen@Sun.COM void * 120*10706SJulian.Pullen@Sun.COM adutils_mutex_alloc(void) 121*10706SJulian.Pullen@Sun.COM { 122*10706SJulian.Pullen@Sun.COM pthread_mutex_t *mutexp; 123*10706SJulian.Pullen@Sun.COM int rc; 124*10706SJulian.Pullen@Sun.COM 125*10706SJulian.Pullen@Sun.COM mutexp = malloc(sizeof (pthread_mutex_t)); 126*10706SJulian.Pullen@Sun.COM if (mutexp == NULL) { 127*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 128*10706SJulian.Pullen@Sun.COM "adutils_mutex_alloc: malloc failed (%s)", 129*10706SJulian.Pullen@Sun.COM strerror(errno)); 130*10706SJulian.Pullen@Sun.COM return (NULL); 131*10706SJulian.Pullen@Sun.COM } 132*10706SJulian.Pullen@Sun.COM 133*10706SJulian.Pullen@Sun.COM rc = pthread_mutex_init(mutexp, NULL); 134*10706SJulian.Pullen@Sun.COM if (rc != 0) { 135*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 136*10706SJulian.Pullen@Sun.COM "adutils_mutex_alloc: " 137*10706SJulian.Pullen@Sun.COM "pthread_mutex_init failed (%s)", 138*10706SJulian.Pullen@Sun.COM strerror(rc)); 139*10706SJulian.Pullen@Sun.COM free(mutexp); 140*10706SJulian.Pullen@Sun.COM return (NULL); 141*10706SJulian.Pullen@Sun.COM } 142*10706SJulian.Pullen@Sun.COM return (mutexp); 143*10706SJulian.Pullen@Sun.COM } 144*10706SJulian.Pullen@Sun.COM 145*10706SJulian.Pullen@Sun.COM /* 146*10706SJulian.Pullen@Sun.COM * Free a mutex. 147*10706SJulian.Pullen@Sun.COM */ 148*10706SJulian.Pullen@Sun.COM static 149*10706SJulian.Pullen@Sun.COM void 150*10706SJulian.Pullen@Sun.COM adutils_mutex_free(void *mutexp) 151*10706SJulian.Pullen@Sun.COM { 152*10706SJulian.Pullen@Sun.COM (void) pthread_mutex_destroy((pthread_mutex_t *)mutexp); 153*10706SJulian.Pullen@Sun.COM free(mutexp); 154*10706SJulian.Pullen@Sun.COM } 155*10706SJulian.Pullen@Sun.COM 156*10706SJulian.Pullen@Sun.COM /* 157*10706SJulian.Pullen@Sun.COM * Get the thread's local errno. 158*10706SJulian.Pullen@Sun.COM */ 159*10706SJulian.Pullen@Sun.COM static 160*10706SJulian.Pullen@Sun.COM int 161*10706SJulian.Pullen@Sun.COM adutils_get_errno(void) 162*10706SJulian.Pullen@Sun.COM { 163*10706SJulian.Pullen@Sun.COM return (errno); 164*10706SJulian.Pullen@Sun.COM } 165*10706SJulian.Pullen@Sun.COM 166*10706SJulian.Pullen@Sun.COM /* 167*10706SJulian.Pullen@Sun.COM * Set the thread's local errno. 168*10706SJulian.Pullen@Sun.COM */ 169*10706SJulian.Pullen@Sun.COM static 170*10706SJulian.Pullen@Sun.COM void 171*10706SJulian.Pullen@Sun.COM adutils_set_errno(int err) 172*10706SJulian.Pullen@Sun.COM { 173*10706SJulian.Pullen@Sun.COM errno = err; 174*10706SJulian.Pullen@Sun.COM } 175*10706SJulian.Pullen@Sun.COM 176*10706SJulian.Pullen@Sun.COM /* 177*10706SJulian.Pullen@Sun.COM * Get a pointer to the thread's local LDAP error state structure. 178*10706SJulian.Pullen@Sun.COM * Lazily allocate the thread-local storage, so that we don't need 179*10706SJulian.Pullen@Sun.COM * initialization when each thread starts. 180*10706SJulian.Pullen@Sun.COM */ 181*10706SJulian.Pullen@Sun.COM static 182*10706SJulian.Pullen@Sun.COM struct adutils_lderrno * 183*10706SJulian.Pullen@Sun.COM adutils_get_lderrno_struct(void) 184*10706SJulian.Pullen@Sun.COM { 185*10706SJulian.Pullen@Sun.COM struct adutils_lderrno *le; 186*10706SJulian.Pullen@Sun.COM int rc; 187*10706SJulian.Pullen@Sun.COM 188*10706SJulian.Pullen@Sun.COM le = pthread_getspecific(adutils_lderrno_key); 189*10706SJulian.Pullen@Sun.COM if (le == NULL) { 190*10706SJulian.Pullen@Sun.COM le = calloc(1, sizeof (*le)); 191*10706SJulian.Pullen@Sun.COM if (le == NULL) { 192*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 193*10706SJulian.Pullen@Sun.COM "adutils_get_lderrno_struct: calloc failed (%s)", 194*10706SJulian.Pullen@Sun.COM strerror(errno)); 195*10706SJulian.Pullen@Sun.COM return (NULL); 196*10706SJulian.Pullen@Sun.COM } 197*10706SJulian.Pullen@Sun.COM rc = pthread_setspecific(adutils_lderrno_key, le); 198*10706SJulian.Pullen@Sun.COM if (rc != 0) { 199*10706SJulian.Pullen@Sun.COM logger(LOG_ERR, 200*10706SJulian.Pullen@Sun.COM "adutils_get_lderrno_struct: " 201*10706SJulian.Pullen@Sun.COM "pthread_setspecific failed (%s)", 202*10706SJulian.Pullen@Sun.COM strerror(rc)); 203*10706SJulian.Pullen@Sun.COM free(le); 204*10706SJulian.Pullen@Sun.COM return (NULL); 205*10706SJulian.Pullen@Sun.COM } 206*10706SJulian.Pullen@Sun.COM } 207*10706SJulian.Pullen@Sun.COM 208*10706SJulian.Pullen@Sun.COM return (le); 209*10706SJulian.Pullen@Sun.COM } 210*10706SJulian.Pullen@Sun.COM 211*10706SJulian.Pullen@Sun.COM /* 212*10706SJulian.Pullen@Sun.COM * Store an error report in the thread's local LDAP error state structure. 213*10706SJulian.Pullen@Sun.COM */ 214*10706SJulian.Pullen@Sun.COM static 215*10706SJulian.Pullen@Sun.COM void 216*10706SJulian.Pullen@Sun.COM adutils_set_lderrno(int err, char *matched, char *errmsg, void *dummy) 217*10706SJulian.Pullen@Sun.COM { 218*10706SJulian.Pullen@Sun.COM NOTE(ARGUNUSED(dummy)) 219*10706SJulian.Pullen@Sun.COM struct adutils_lderrno *le; 220*10706SJulian.Pullen@Sun.COM 221*10706SJulian.Pullen@Sun.COM le = adutils_get_lderrno_struct(); 222*10706SJulian.Pullen@Sun.COM if (le != NULL) { 223*10706SJulian.Pullen@Sun.COM le->le_errno = err; 224*10706SJulian.Pullen@Sun.COM if (le->le_matched != NULL) 225*10706SJulian.Pullen@Sun.COM ldap_memfree(le->le_matched); 226*10706SJulian.Pullen@Sun.COM le->le_matched = matched; 227*10706SJulian.Pullen@Sun.COM if (le->le_errmsg != NULL) 228*10706SJulian.Pullen@Sun.COM ldap_memfree(le->le_errmsg); 229*10706SJulian.Pullen@Sun.COM le->le_errmsg = errmsg; 230*10706SJulian.Pullen@Sun.COM } 231*10706SJulian.Pullen@Sun.COM } 232*10706SJulian.Pullen@Sun.COM 233*10706SJulian.Pullen@Sun.COM /* 234*10706SJulian.Pullen@Sun.COM * Retrieve an error report from the thread's local LDAP error state structure. 235*10706SJulian.Pullen@Sun.COM */ 236*10706SJulian.Pullen@Sun.COM static 237*10706SJulian.Pullen@Sun.COM int 238*10706SJulian.Pullen@Sun.COM adutils_get_lderrno(char **matched, char **errmsg, void *dummy) 239*10706SJulian.Pullen@Sun.COM { 240*10706SJulian.Pullen@Sun.COM NOTE(ARGUNUSED(dummy)) 241*10706SJulian.Pullen@Sun.COM struct adutils_lderrno *le; 242*10706SJulian.Pullen@Sun.COM static struct adutils_lderrno empty = { LDAP_SUCCESS, NULL, NULL }; 243*10706SJulian.Pullen@Sun.COM 244*10706SJulian.Pullen@Sun.COM le = adutils_get_lderrno_struct(); 245*10706SJulian.Pullen@Sun.COM if (le == NULL) 246*10706SJulian.Pullen@Sun.COM le = ∅ 247*10706SJulian.Pullen@Sun.COM 248*10706SJulian.Pullen@Sun.COM if (matched != NULL) 249*10706SJulian.Pullen@Sun.COM *matched = le->le_matched; 250*10706SJulian.Pullen@Sun.COM if (errmsg != NULL) 251*10706SJulian.Pullen@Sun.COM *errmsg = le->le_errmsg; 252*10706SJulian.Pullen@Sun.COM return (le->le_errno); 253*10706SJulian.Pullen@Sun.COM } 254*10706SJulian.Pullen@Sun.COM 255*10706SJulian.Pullen@Sun.COM /* 256*10706SJulian.Pullen@Sun.COM * Free the thread's local LDAP error state structure. 257*10706SJulian.Pullen@Sun.COM */ 258*10706SJulian.Pullen@Sun.COM static 259*10706SJulian.Pullen@Sun.COM void 260*10706SJulian.Pullen@Sun.COM adutils_lderrno_destructor(void *tsd) 261*10706SJulian.Pullen@Sun.COM { 262*10706SJulian.Pullen@Sun.COM struct adutils_lderrno *le = tsd; 263*10706SJulian.Pullen@Sun.COM 264*10706SJulian.Pullen@Sun.COM if (le == NULL) 265*10706SJulian.Pullen@Sun.COM return; 266*10706SJulian.Pullen@Sun.COM 267*10706SJulian.Pullen@Sun.COM if (le->le_matched != NULL) { 268*10706SJulian.Pullen@Sun.COM ldap_memfree(le->le_matched); 269*10706SJulian.Pullen@Sun.COM le->le_matched = NULL; 270*10706SJulian.Pullen@Sun.COM } 271*10706SJulian.Pullen@Sun.COM if (le->le_errmsg != NULL) { 272*10706SJulian.Pullen@Sun.COM ldap_memfree(le->le_errmsg); 273*10706SJulian.Pullen@Sun.COM le->le_errmsg = NULL; 274*10706SJulian.Pullen@Sun.COM } 275*10706SJulian.Pullen@Sun.COM free(le); 276*10706SJulian.Pullen@Sun.COM } 277