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