xref: /titanic_44/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <assert.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <memory.h>
32*7c478bd9Sstevel@tonic-gate #include <signal.h>
33*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <string.h>
36*7c478bd9Sstevel@tonic-gate #include <libintl.h>
37*7c478bd9Sstevel@tonic-gate #include <syslog.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/door.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
43*7c478bd9Sstevel@tonic-gate #include <synch.h>
44*7c478bd9Sstevel@tonic-gate #include <pthread.h>
45*7c478bd9Sstevel@tonic-gate #include <unistd.h>
46*7c478bd9Sstevel@tonic-gate #include <lber.h>
47*7c478bd9Sstevel@tonic-gate #include <ldap.h>
48*7c478bd9Sstevel@tonic-gate #include <ctype.h>	/* tolower */
49*7c478bd9Sstevel@tonic-gate #include "cachemgr.h"
50*7c478bd9Sstevel@tonic-gate #include "solaris-priv.h"
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate static rwlock_t	ldap_lock = DEFAULTRWLOCK;
53*7c478bd9Sstevel@tonic-gate static int	sighup_update = FALSE;
54*7c478bd9Sstevel@tonic-gate extern admin_t	current_admin;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /* variables used for SIGHUP wakeup on sleep */
57*7c478bd9Sstevel@tonic-gate static mutex_t			sighuplock;
58*7c478bd9Sstevel@tonic-gate static cond_t			cond;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /* refresh time statistics */
61*7c478bd9Sstevel@tonic-gate static time_t	prev_refresh_time = 0;
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /* variables used for signaling parent process */
64*7c478bd9Sstevel@tonic-gate static mutex_t	sig_mutex;
65*7c478bd9Sstevel@tonic-gate static int	signal_done = FALSE;
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* TCP connection timeout (in milliseconds) */
68*7c478bd9Sstevel@tonic-gate static int tcptimeout = NS_DEFAULT_BIND_TIMEOUT * 1000;
69*7c478bd9Sstevel@tonic-gate /* search timeout (in seconds) */
70*7c478bd9Sstevel@tonic-gate static int search_timeout = NS_DEFAULT_SEARCH_TIMEOUT;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #ifdef SLP
73*7c478bd9Sstevel@tonic-gate extern int	use_slp;
74*7c478bd9Sstevel@tonic-gate #endif /* SLP */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* nis domain information */
77*7c478bd9Sstevel@tonic-gate #define	_NIS_FILTER		"objectclass=nisDomainObject"
78*7c478bd9Sstevel@tonic-gate #define	_NIS_DOMAIN		"nisdomain"
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate #define	CACHESLEEPTIME		600
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * server list refresh delay when in "no server" mode
83*7c478bd9Sstevel@tonic-gate  * (1 second)
84*7c478bd9Sstevel@tonic-gate  */
85*7c478bd9Sstevel@tonic-gate #define	REFRESH_DELAY_WHEN_NO_SERVER	1
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate typedef enum {
88*7c478bd9Sstevel@tonic-gate 	INFO_OP_CREATE		= 0,
89*7c478bd9Sstevel@tonic-gate 	INFO_OP_DELETE		= 1,
90*7c478bd9Sstevel@tonic-gate 	INFO_OP_REFRESH		= 2,
91*7c478bd9Sstevel@tonic-gate 	INFO_OP_REFRESH_WAIT	= 3,
92*7c478bd9Sstevel@tonic-gate 	INFO_OP_GETSERVER	= 4,
93*7c478bd9Sstevel@tonic-gate 	INFO_OP_GETSTAT		= 5
94*7c478bd9Sstevel@tonic-gate } info_op_t;
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate typedef enum {
97*7c478bd9Sstevel@tonic-gate 	INFO_RW_UNKNOWN		= 0,
98*7c478bd9Sstevel@tonic-gate 	INFO_RW_READONLY	= 1,
99*7c478bd9Sstevel@tonic-gate 	INFO_RW_WRITEABLE	= 2
100*7c478bd9Sstevel@tonic-gate } info_rw_t;
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate typedef enum {
103*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_JUST_INITED	= -1,
104*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_UNKNOWN	= 0,
105*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_CONNECTING	= 1,
106*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_UP		= 2,
107*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_ERROR 	= 3,
108*7c478bd9Sstevel@tonic-gate 	INFO_SERVER_REMOVED	= 4
109*7c478bd9Sstevel@tonic-gate } info_server_t;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate typedef enum {
112*7c478bd9Sstevel@tonic-gate 	INFO_STATUS_UNKNOWN	= 0,
113*7c478bd9Sstevel@tonic-gate 	INFO_STATUS_ERROR 	= 1,
114*7c478bd9Sstevel@tonic-gate 	INFO_STATUS_NEW   	= 2,
115*7c478bd9Sstevel@tonic-gate 	INFO_STATUS_OLD		= 3
116*7c478bd9Sstevel@tonic-gate } info_status_t;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate typedef enum {
119*7c478bd9Sstevel@tonic-gate 	CACHE_OP_CREATE		= 0,
120*7c478bd9Sstevel@tonic-gate 	CACHE_OP_DELETE		= 1,
121*7c478bd9Sstevel@tonic-gate 	CACHE_OP_FIND		= 2,
122*7c478bd9Sstevel@tonic-gate 	CACHE_OP_ADD		= 3,
123*7c478bd9Sstevel@tonic-gate 	CACHE_OP_GETSTAT	= 4
124*7c478bd9Sstevel@tonic-gate } cache_op_t;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate typedef enum {
127*7c478bd9Sstevel@tonic-gate 	CACHE_MAP_UNKNOWN	= 0,
128*7c478bd9Sstevel@tonic-gate 	CACHE_MAP_DN2DOMAIN	= 1
129*7c478bd9Sstevel@tonic-gate } cache_type_t;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate typedef struct server_info_ext {
132*7c478bd9Sstevel@tonic-gate 	char			*addr;
133*7c478bd9Sstevel@tonic-gate 	char			*rootDSE_data;
134*7c478bd9Sstevel@tonic-gate 	char			*errormsg;
135*7c478bd9Sstevel@tonic-gate 	info_rw_t		type;
136*7c478bd9Sstevel@tonic-gate 	info_server_t		server_status;
137*7c478bd9Sstevel@tonic-gate 	info_server_t		prev_server_status;
138*7c478bd9Sstevel@tonic-gate 	info_status_t 		info_status;
139*7c478bd9Sstevel@tonic-gate } server_info_ext_t;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate typedef struct server_info {
142*7c478bd9Sstevel@tonic-gate 	struct server_info 	*next;
143*7c478bd9Sstevel@tonic-gate 	mutex_t			mutex[2];	/* 0: current copy lock */
144*7c478bd9Sstevel@tonic-gate 						/* 1: update copy lock */
145*7c478bd9Sstevel@tonic-gate 	server_info_ext_t	sinfo[2]; /* 0: current, 1:  update copy */
146*7c478bd9Sstevel@tonic-gate } server_info_t;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate typedef struct cache_hash {
149*7c478bd9Sstevel@tonic-gate 	cache_type_t		type;
150*7c478bd9Sstevel@tonic-gate 	char			*from;
151*7c478bd9Sstevel@tonic-gate 	char			*to;
152*7c478bd9Sstevel@tonic-gate 	struct cache_hash	*next;
153*7c478bd9Sstevel@tonic-gate } cache_hash_t;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate static int getldap_destroy_serverInfo(server_info_t *head);
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate /*
158*7c478bd9Sstevel@tonic-gate  * Load configuration
159*7c478bd9Sstevel@tonic-gate  * The code was in signal handler getldap_revalidate
160*7c478bd9Sstevel@tonic-gate  * It's moved out of the handler because it could cause deadlock
161*7c478bd9Sstevel@tonic-gate  * return: 1 SUCCESS
162*7c478bd9Sstevel@tonic-gate  *         0 FAIL
163*7c478bd9Sstevel@tonic-gate  */
164*7c478bd9Sstevel@tonic-gate static int
165*7c478bd9Sstevel@tonic-gate load_config() {
166*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *error;
167*7c478bd9Sstevel@tonic-gate 	int		rc = 1;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_setServer(TRUE);
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&ldap_lock);
172*7c478bd9Sstevel@tonic-gate 	if ((error = __ns_ldap_LoadConfiguration()) != NULL) {
173*7c478bd9Sstevel@tonic-gate 		logit("Error: Unable to read '%s': %s\n",
174*7c478bd9Sstevel@tonic-gate 			NSCONFIGFILE, error->message);
175*7c478bd9Sstevel@tonic-gate 		__ns_ldap_freeError(&error);
176*7c478bd9Sstevel@tonic-gate 		rc = 0; /* FAIL */
177*7c478bd9Sstevel@tonic-gate 	} else
178*7c478bd9Sstevel@tonic-gate 		sighup_update = TRUE;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	return (rc);
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate /*
186*7c478bd9Sstevel@tonic-gate  * Calculate a hash for a string
187*7c478bd9Sstevel@tonic-gate  * Based on elf_hash algorithm, hash is case insensitive
188*7c478bd9Sstevel@tonic-gate  * Uses tolower instead of _tolower because of I18N
189*7c478bd9Sstevel@tonic-gate  */
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate static unsigned long
192*7c478bd9Sstevel@tonic-gate getldap_hash(const char *str)
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate 	unsigned int	hval = 0;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	while (*str) {
197*7c478bd9Sstevel@tonic-gate 		unsigned int	g;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 		hval = (hval << 4) + tolower(*str++);
200*7c478bd9Sstevel@tonic-gate 		if ((g = (hval & 0xf0000000)) != 0)
201*7c478bd9Sstevel@tonic-gate 			hval ^= g >> 24;
202*7c478bd9Sstevel@tonic-gate 		hval &= ~g;
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate 	return ((unsigned long)hval);
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate /*
208*7c478bd9Sstevel@tonic-gate  * Remove a hash table entry.
209*7c478bd9Sstevel@tonic-gate  * This function expects a lock in place when called.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate static cache_hash_t *
213*7c478bd9Sstevel@tonic-gate getldap_free_hash(cache_hash_t *p)
214*7c478bd9Sstevel@tonic-gate {
215*7c478bd9Sstevel@tonic-gate 	cache_hash_t	*next;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	p->type = CACHE_MAP_UNKNOWN;
218*7c478bd9Sstevel@tonic-gate 	if (p->from)
219*7c478bd9Sstevel@tonic-gate 		free(p->from);
220*7c478bd9Sstevel@tonic-gate 	if (p->to)
221*7c478bd9Sstevel@tonic-gate 		free(p->to);
222*7c478bd9Sstevel@tonic-gate 	next = p->next;
223*7c478bd9Sstevel@tonic-gate 	p->next = NULL;
224*7c478bd9Sstevel@tonic-gate 	free(p);
225*7c478bd9Sstevel@tonic-gate 	return (next);
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate /*
229*7c478bd9Sstevel@tonic-gate  * Scan a hash table hit for a matching hash entry.
230*7c478bd9Sstevel@tonic-gate  * This function expects a lock in place when called.
231*7c478bd9Sstevel@tonic-gate  */
232*7c478bd9Sstevel@tonic-gate static cache_hash_t *
233*7c478bd9Sstevel@tonic-gate getldap_scan_hash(cache_type_t type, char *from,
234*7c478bd9Sstevel@tonic-gate 		cache_hash_t *idx)
235*7c478bd9Sstevel@tonic-gate {
236*7c478bd9Sstevel@tonic-gate 	while (idx) {
237*7c478bd9Sstevel@tonic-gate 		if (idx->type == type &&
238*7c478bd9Sstevel@tonic-gate 		    strcasecmp(from, idx->from) == 0) {
239*7c478bd9Sstevel@tonic-gate 			return (idx);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 		idx = idx->next;
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 	return ((cache_hash_t *)NULL);
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate /*
247*7c478bd9Sstevel@tonic-gate  * Format and return the cache data statistics
248*7c478bd9Sstevel@tonic-gate  */
249*7c478bd9Sstevel@tonic-gate static int
250*7c478bd9Sstevel@tonic-gate getldap_get_cacheData_stat(int max, int current, char **output)
251*7c478bd9Sstevel@tonic-gate {
252*7c478bd9Sstevel@tonic-gate #define	C_HEADER0	"Cache data information: "
253*7c478bd9Sstevel@tonic-gate #define	C_HEADER1	"  Maximum cache entries:   "
254*7c478bd9Sstevel@tonic-gate #define	C_HEADER2	"  Number of cache entries: "
255*7c478bd9Sstevel@tonic-gate 	int		hdr0_len = strlen(gettext(C_HEADER0));
256*7c478bd9Sstevel@tonic-gate 	int		hdr1_len = strlen(gettext(C_HEADER1));
257*7c478bd9Sstevel@tonic-gate 	int		hdr2_len = strlen(gettext(C_HEADER2));
258*7c478bd9Sstevel@tonic-gate 	int		len;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
261*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_cacheData_stat()...\n");
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	*output = NULL;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	len = hdr0_len + hdr1_len + hdr2_len +
267*7c478bd9Sstevel@tonic-gate 		3 * strlen(DOORLINESEP) + 21;
268*7c478bd9Sstevel@tonic-gate 	*output = malloc(len);
269*7c478bd9Sstevel@tonic-gate 	if (*output == NULL)
270*7c478bd9Sstevel@tonic-gate 		return (-1);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	(void) snprintf(*output, len, "%s%s%s%10d%s%s%10d%s",
273*7c478bd9Sstevel@tonic-gate 		gettext(C_HEADER0), DOORLINESEP,
274*7c478bd9Sstevel@tonic-gate 		gettext(C_HEADER1), max, DOORLINESEP,
275*7c478bd9Sstevel@tonic-gate 		gettext(C_HEADER2), current, DOORLINESEP);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate static int
281*7c478bd9Sstevel@tonic-gate getldap_cache_op(cache_op_t op, cache_type_t type,
282*7c478bd9Sstevel@tonic-gate 			char *from, char **to)
283*7c478bd9Sstevel@tonic-gate {
284*7c478bd9Sstevel@tonic-gate #define	CACHE_HASH_MAX		257
285*7c478bd9Sstevel@tonic-gate #define	CACHE_HASH_MAX_ENTRY	256
286*7c478bd9Sstevel@tonic-gate 	static cache_hash_t	*hashTbl[CACHE_HASH_MAX];
287*7c478bd9Sstevel@tonic-gate 	cache_hash_t		*next, *idx, *newp;
288*7c478bd9Sstevel@tonic-gate 	unsigned long		hash;
289*7c478bd9Sstevel@tonic-gate 	static rwlock_t 	cache_lock = DEFAULTRWLOCK;
290*7c478bd9Sstevel@tonic-gate 	int 			i;
291*7c478bd9Sstevel@tonic-gate 	static			entry_num = 0;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
294*7c478bd9Sstevel@tonic-gate 		logit("getldap_cache_op()...\n");
295*7c478bd9Sstevel@tonic-gate 	}
296*7c478bd9Sstevel@tonic-gate 	switch (op) {
297*7c478bd9Sstevel@tonic-gate 	case CACHE_OP_CREATE:
298*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
299*7c478bd9Sstevel@tonic-gate 			logit("operation is CACHE_OP_CREATE...\n");
300*7c478bd9Sstevel@tonic-gate 		}
301*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&cache_lock);
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < CACHE_HASH_MAX; i++) {
304*7c478bd9Sstevel@tonic-gate 			hashTbl[i] = NULL;
305*7c478bd9Sstevel@tonic-gate 		}
306*7c478bd9Sstevel@tonic-gate 		entry_num = 0;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&cache_lock);
309*7c478bd9Sstevel@tonic-gate 		break;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	case CACHE_OP_DELETE:
312*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
313*7c478bd9Sstevel@tonic-gate 			logit("operation is CACHE_OP_DELETE...\n");
314*7c478bd9Sstevel@tonic-gate 		}
315*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&cache_lock);
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < CACHE_HASH_MAX; i++) {
318*7c478bd9Sstevel@tonic-gate 			next = hashTbl[i];
319*7c478bd9Sstevel@tonic-gate 			while (next != NULL) {
320*7c478bd9Sstevel@tonic-gate 				next = getldap_free_hash(next);
321*7c478bd9Sstevel@tonic-gate 			}
322*7c478bd9Sstevel@tonic-gate 			hashTbl[i] = NULL;
323*7c478bd9Sstevel@tonic-gate 		}
324*7c478bd9Sstevel@tonic-gate 		entry_num = 0;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&cache_lock);
327*7c478bd9Sstevel@tonic-gate 		break;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	case CACHE_OP_ADD:
330*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
331*7c478bd9Sstevel@tonic-gate 			logit("operation is CACHE_OP_ADD...\n");
332*7c478bd9Sstevel@tonic-gate 		}
333*7c478bd9Sstevel@tonic-gate 		if (from == NULL || to == NULL || *to == NULL)
334*7c478bd9Sstevel@tonic-gate 			return (-1);
335*7c478bd9Sstevel@tonic-gate 		hash = getldap_hash(from) % CACHE_HASH_MAX;
336*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&cache_lock);
337*7c478bd9Sstevel@tonic-gate 		idx = hashTbl[hash];
338*7c478bd9Sstevel@tonic-gate 		/*
339*7c478bd9Sstevel@tonic-gate 		 * replace old "to" value with new one
340*7c478bd9Sstevel@tonic-gate 		 * if an entry with same "from"
341*7c478bd9Sstevel@tonic-gate 		 * already exists
342*7c478bd9Sstevel@tonic-gate 		 */
343*7c478bd9Sstevel@tonic-gate 		if (idx) {
344*7c478bd9Sstevel@tonic-gate 			newp = getldap_scan_hash(type, from, idx);
345*7c478bd9Sstevel@tonic-gate 			if (newp) {
346*7c478bd9Sstevel@tonic-gate 				free(newp->to);
347*7c478bd9Sstevel@tonic-gate 				newp->to = strdup(*to);
348*7c478bd9Sstevel@tonic-gate 				(void) rw_unlock(&cache_lock);
349*7c478bd9Sstevel@tonic-gate 				return (NS_LDAP_SUCCESS);
350*7c478bd9Sstevel@tonic-gate 			}
351*7c478bd9Sstevel@tonic-gate 		}
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		if (entry_num > CACHE_HASH_MAX_ENTRY) {
354*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&cache_lock);
355*7c478bd9Sstevel@tonic-gate 			return (-1);
356*7c478bd9Sstevel@tonic-gate 		}
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 		newp = (cache_hash_t *)malloc(sizeof (cache_hash_t));
359*7c478bd9Sstevel@tonic-gate 		if (newp == NULL) {
360*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&cache_lock);
361*7c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
362*7c478bd9Sstevel@tonic-gate 		}
363*7c478bd9Sstevel@tonic-gate 		newp->type = type;
364*7c478bd9Sstevel@tonic-gate 		newp->from = strdup(from);
365*7c478bd9Sstevel@tonic-gate 		newp->to = strdup(*to);
366*7c478bd9Sstevel@tonic-gate 		newp->next = idx;
367*7c478bd9Sstevel@tonic-gate 		hashTbl[hash] = newp;
368*7c478bd9Sstevel@tonic-gate 		entry_num++;
369*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&cache_lock);
370*7c478bd9Sstevel@tonic-gate 		break;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	case CACHE_OP_FIND:
373*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
374*7c478bd9Sstevel@tonic-gate 			logit("operation is CACHE_OP_FIND...\n");
375*7c478bd9Sstevel@tonic-gate 		}
376*7c478bd9Sstevel@tonic-gate 		if (from == NULL || to == NULL)
377*7c478bd9Sstevel@tonic-gate 			return (-1);
378*7c478bd9Sstevel@tonic-gate 		*to = NULL;
379*7c478bd9Sstevel@tonic-gate 		hash = getldap_hash(from) % CACHE_HASH_MAX;
380*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&cache_lock);
381*7c478bd9Sstevel@tonic-gate 		idx = hashTbl[hash];
382*7c478bd9Sstevel@tonic-gate 		idx = getldap_scan_hash(type, from, idx);
383*7c478bd9Sstevel@tonic-gate 		if (idx)
384*7c478bd9Sstevel@tonic-gate 			*to = strdup(idx->to);
385*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&cache_lock);
386*7c478bd9Sstevel@tonic-gate 		if (idx == NULL)
387*7c478bd9Sstevel@tonic-gate 			return (-1);
388*7c478bd9Sstevel@tonic-gate 		break;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	case CACHE_OP_GETSTAT:
391*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
392*7c478bd9Sstevel@tonic-gate 			logit("operation is CACHE_OP_GETSTAT...\n");
393*7c478bd9Sstevel@tonic-gate 		}
394*7c478bd9Sstevel@tonic-gate 		if (to == NULL)
395*7c478bd9Sstevel@tonic-gate 			return (-1);
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 		return (getldap_get_cacheData_stat(CACHE_HASH_MAX_ENTRY,
398*7c478bd9Sstevel@tonic-gate 				entry_num, to));
399*7c478bd9Sstevel@tonic-gate 		break;
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	default:
402*7c478bd9Sstevel@tonic-gate 		logit("getldap_cache_op(): "
403*7c478bd9Sstevel@tonic-gate 			"invalid operation code (%d).\n", op);
404*7c478bd9Sstevel@tonic-gate 		return (-1);
405*7c478bd9Sstevel@tonic-gate 		break;
406*7c478bd9Sstevel@tonic-gate 	}
407*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate /*
410*7c478bd9Sstevel@tonic-gate  * Function: sync_current_with_update_copy
411*7c478bd9Sstevel@tonic-gate  *
412*7c478bd9Sstevel@tonic-gate  * This function syncs up the 2 sinfo copies in info.
413*7c478bd9Sstevel@tonic-gate  *
414*7c478bd9Sstevel@tonic-gate  * The 2 copies are identical most of time.
415*7c478bd9Sstevel@tonic-gate  * The update copy(sinfo[1]) could be different when
416*7c478bd9Sstevel@tonic-gate  * getldap_serverInfo_refresh thread is refreshing the server list
417*7c478bd9Sstevel@tonic-gate  * and calls getldap_get_rootDSE to update info.  getldap_get_rootDSE
418*7c478bd9Sstevel@tonic-gate  * calls sync_current_with_update_copy to sync up 2 copies before thr_exit.
419*7c478bd9Sstevel@tonic-gate  * The calling sequence is
420*7c478bd9Sstevel@tonic-gate  *  getldap_serverInfo_refresh->
421*7c478bd9Sstevel@tonic-gate  *  getldap_get_serverInfo_op(INFO_OP_CREATE,...)->
422*7c478bd9Sstevel@tonic-gate  *  getldap_set_serverInfo->
423*7c478bd9Sstevel@tonic-gate  *  getldap_get_rootDSE
424*7c478bd9Sstevel@tonic-gate  *
425*7c478bd9Sstevel@tonic-gate  * The original server_info_t has one copy of server info. When libsldap
426*7c478bd9Sstevel@tonic-gate  * makes door call GETLDAPSERVER to get the server info and getldap_get_rootDSE
427*7c478bd9Sstevel@tonic-gate  * is updating the server info, it would hit a unprotected window in
428*7c478bd9Sstevel@tonic-gate  * getldap_rootDSE. The door call  will not get server info and libsldap
429*7c478bd9Sstevel@tonic-gate  * fails at making ldap connection.
430*7c478bd9Sstevel@tonic-gate  *
431*7c478bd9Sstevel@tonic-gate  * The new server_info_t provides GETLDAPSERVER thread with a current
432*7c478bd9Sstevel@tonic-gate  * copy(sinfo[0]). getldap_get_rootDSE only works on the update copy(sinfo[1])
433*7c478bd9Sstevel@tonic-gate  * and syncs up 2 copies before thr_exit. This will close the window in
434*7c478bd9Sstevel@tonic-gate  * getldap_get_rootDSE.
435*7c478bd9Sstevel@tonic-gate  *
436*7c478bd9Sstevel@tonic-gate  */
437*7c478bd9Sstevel@tonic-gate static void
438*7c478bd9Sstevel@tonic-gate sync_current_with_update_copy(server_info_t *info)
439*7c478bd9Sstevel@tonic-gate {
440*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
441*7c478bd9Sstevel@tonic-gate 		logit("sync_current_with_update_copy()...\n");
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&info->mutex[1]);
445*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&info->mutex[0]);
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	/* free memory in current copy first */
448*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[0].addr)
449*7c478bd9Sstevel@tonic-gate 		free(info->sinfo[0].addr);
450*7c478bd9Sstevel@tonic-gate 	info->sinfo[0].addr = NULL;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[0].rootDSE_data)
453*7c478bd9Sstevel@tonic-gate 		free(info->sinfo[0].rootDSE_data);
454*7c478bd9Sstevel@tonic-gate 	info->sinfo[0].rootDSE_data = NULL;
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[0].errormsg)
457*7c478bd9Sstevel@tonic-gate 		free(info->sinfo[0].errormsg);
458*7c478bd9Sstevel@tonic-gate 	info->sinfo[0].errormsg = NULL;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	/*
461*7c478bd9Sstevel@tonic-gate 	 * make current and update copy identical
462*7c478bd9Sstevel@tonic-gate 	 */
463*7c478bd9Sstevel@tonic-gate 	info->sinfo[0] = info->sinfo[1];
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 	/*
466*7c478bd9Sstevel@tonic-gate 	 * getldap_get_server_stat() reads the update copy sinfo[1]
467*7c478bd9Sstevel@tonic-gate 	 * so it can't be freed or nullified yet at this point.
468*7c478bd9Sstevel@tonic-gate 	 *
469*7c478bd9Sstevel@tonic-gate 	 * The sinfo[0] and sinfo[1] have identical string pointers.
470*7c478bd9Sstevel@tonic-gate 	 * strdup the strings to avoid the double free problem.
471*7c478bd9Sstevel@tonic-gate 	 * The strings of sinfo[1] are freed in
472*7c478bd9Sstevel@tonic-gate 	 * getldap_get_rootDSE() and the strings of sinfo[0]
473*7c478bd9Sstevel@tonic-gate 	 * are freed earlier in this function. If the pointers are the
474*7c478bd9Sstevel@tonic-gate 	 * same, they will be freed twice.
475*7c478bd9Sstevel@tonic-gate 	 */
476*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[1].addr)
477*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].addr = strdup(info->sinfo[1].addr);
478*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[1].rootDSE_data)
479*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].rootDSE_data =
480*7c478bd9Sstevel@tonic-gate 				strdup(info->sinfo[1].rootDSE_data);
481*7c478bd9Sstevel@tonic-gate 	if (info->sinfo[1].errormsg)
482*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].errormsg = strdup(info->sinfo[1].errormsg);
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&info->mutex[0]);
485*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&info->mutex[1]);
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate }
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate static void *
490*7c478bd9Sstevel@tonic-gate getldap_get_rootDSE(void *arg)
491*7c478bd9Sstevel@tonic-gate {
492*7c478bd9Sstevel@tonic-gate 	server_info_t	*serverInfo = (server_info_t *)arg;
493*7c478bd9Sstevel@tonic-gate 	int 		ldapVersion = LDAP_VERSION3;
494*7c478bd9Sstevel@tonic-gate 	LDAP		*ld;
495*7c478bd9Sstevel@tonic-gate 	LDAPMessage	*resultMsg = NULL;
496*7c478bd9Sstevel@tonic-gate 	LDAPMessage	*e;
497*7c478bd9Sstevel@tonic-gate 	BerElement	*ber;
498*7c478bd9Sstevel@tonic-gate 	char		errmsg[MAXERROR];
499*7c478bd9Sstevel@tonic-gate 	char		*rootDSE;
500*7c478bd9Sstevel@tonic-gate 	char		*attrs[3];
501*7c478bd9Sstevel@tonic-gate 	char		*a;
502*7c478bd9Sstevel@tonic-gate 	char		**vals;
503*7c478bd9Sstevel@tonic-gate 	int		ldaperrno = 0;
504*7c478bd9Sstevel@tonic-gate 	int		rc = 0, exitrc = NS_LDAP_SUCCESS;
505*7c478bd9Sstevel@tonic-gate 	int		i = 0, len = 0;
506*7c478bd9Sstevel@tonic-gate 	pid_t		ppid;
507*7c478bd9Sstevel@tonic-gate 	struct timeval	tv;
508*7c478bd9Sstevel@tonic-gate 	int		server_found = 0;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
511*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_rootDSE()....\n");
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	/* initialize the server info element */
515*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&serverInfo->mutex[1]);
516*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].type	= INFO_RW_UNKNOWN;
517*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].info_status
518*7c478bd9Sstevel@tonic-gate 				= INFO_STATUS_UNKNOWN;
519*7c478bd9Sstevel@tonic-gate 	/*
520*7c478bd9Sstevel@tonic-gate 	 * When the sever list is refreshed over and over,
521*7c478bd9Sstevel@tonic-gate 	 * this function is called each time it is refreshed.
522*7c478bd9Sstevel@tonic-gate 	 * The previous server status of the update copy(sinfo[1])
523*7c478bd9Sstevel@tonic-gate 	 * is the status of the current copy
524*7c478bd9Sstevel@tonic-gate 	 */
525*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&serverInfo->mutex[0]);
526*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].prev_server_status =
527*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[0].server_status;
528*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&serverInfo->mutex[0]);
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].server_status =
531*7c478bd9Sstevel@tonic-gate 			INFO_SERVER_UNKNOWN;
532*7c478bd9Sstevel@tonic-gate 	if (serverInfo->sinfo[1].rootDSE_data)
533*7c478bd9Sstevel@tonic-gate 		free(serverInfo->sinfo[1].rootDSE_data);
534*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].rootDSE_data	= NULL;
535*7c478bd9Sstevel@tonic-gate 	if (serverInfo->sinfo[1].errormsg)
536*7c478bd9Sstevel@tonic-gate 		free(serverInfo->sinfo[1].errormsg);
537*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].errormsg 		= NULL;
538*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&serverInfo->mutex[1]);
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	if ((ld = ldap_init(serverInfo->sinfo[1].addr,
541*7c478bd9Sstevel@tonic-gate 		LDAP_PORT)) == NULL ||
542*7c478bd9Sstevel@tonic-gate 		/* SKIP ldap data base to prevent recursion */
543*7c478bd9Sstevel@tonic-gate 		/* in gethostbyname when resolving hostname */
544*7c478bd9Sstevel@tonic-gate 		0 != ldap_set_option(ld, LDAP_X_OPT_DNS_SKIPDB, "ldap")) {
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&serverInfo->mutex[1]);
547*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].server_status =
548*7c478bd9Sstevel@tonic-gate 				INFO_SERVER_ERROR;
549*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].info_status =
550*7c478bd9Sstevel@tonic-gate 				INFO_STATUS_ERROR;
551*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].errormsg =
552*7c478bd9Sstevel@tonic-gate 				strdup(gettext("ldap_init failed"));
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
555*7c478bd9Sstevel@tonic-gate 			logit("getldap_get_rootDSE: %s.\n",
556*7c478bd9Sstevel@tonic-gate 			serverInfo->sinfo[1].errormsg);
557*7c478bd9Sstevel@tonic-gate 		}
558*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&serverInfo->mutex[1]);
559*7c478bd9Sstevel@tonic-gate 		/*
560*7c478bd9Sstevel@tonic-gate 		 * sync sinfo copies in the serverInfo.
561*7c478bd9Sstevel@tonic-gate 		 * protected by mutex
562*7c478bd9Sstevel@tonic-gate 		 */
563*7c478bd9Sstevel@tonic-gate 		sync_current_with_update_copy(serverInfo);
564*7c478bd9Sstevel@tonic-gate 		thr_exit((void *) -1);
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	ldap_set_option(ld,
568*7c478bd9Sstevel@tonic-gate 			LDAP_OPT_PROTOCOL_VERSION, &ldapVersion);
569*7c478bd9Sstevel@tonic-gate 	ldap_set_option(ld,
570*7c478bd9Sstevel@tonic-gate 			LDAP_X_OPT_CONNECT_TIMEOUT, &tcptimeout);
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	/* currently, only interested in two attributes */
573*7c478bd9Sstevel@tonic-gate 	attrs[0] = "supportedControl";
574*7c478bd9Sstevel@tonic-gate 	attrs[1] = "supportedsaslmechanisms";
575*7c478bd9Sstevel@tonic-gate 	attrs[2] = NULL;
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&serverInfo->mutex[1]);
578*7c478bd9Sstevel@tonic-gate 	serverInfo->sinfo[1].server_status = INFO_SERVER_CONNECTING;
579*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&serverInfo->mutex[1]);
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	tv.tv_sec = search_timeout;
582*7c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 	rc = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE,
585*7c478bd9Sstevel@tonic-gate 		"(objectclass=*)",
586*7c478bd9Sstevel@tonic-gate 		attrs, 0, NULL, NULL, &tv, 0, &resultMsg);
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	switch (rc) {
589*7c478bd9Sstevel@tonic-gate 		/* If successful, the root DSE was found. */
590*7c478bd9Sstevel@tonic-gate 		case LDAP_SUCCESS:
591*7c478bd9Sstevel@tonic-gate 			break;
592*7c478bd9Sstevel@tonic-gate 		/*
593*7c478bd9Sstevel@tonic-gate 		 * If the root DSE was not found, the server does
594*7c478bd9Sstevel@tonic-gate 		 * not comply with the LDAP v3 protocol.
595*7c478bd9Sstevel@tonic-gate 		 */
596*7c478bd9Sstevel@tonic-gate 		default:
597*7c478bd9Sstevel@tonic-gate 			ldap_get_option(ld,
598*7c478bd9Sstevel@tonic-gate 				LDAP_OPT_ERROR_NUMBER, &ldaperrno);
599*7c478bd9Sstevel@tonic-gate 			(void) snprintf(errmsg, sizeof (errmsg),
600*7c478bd9Sstevel@tonic-gate 				gettext(ldap_err2string(ldaperrno)));
601*7c478bd9Sstevel@tonic-gate 			if (current_admin.debug_level >= DBG_ALL) {
602*7c478bd9Sstevel@tonic-gate 			logit("getldap_get_rootDSE: Root DSE not found."
603*7c478bd9Sstevel@tonic-gate 					" %s is not an LDAPv3 server (%s).\n",
604*7c478bd9Sstevel@tonic-gate 					serverInfo->sinfo[1].addr, errmsg);
605*7c478bd9Sstevel@tonic-gate 			}
606*7c478bd9Sstevel@tonic-gate 			(void) mutex_lock(&serverInfo->mutex[1]);
607*7c478bd9Sstevel@tonic-gate 			serverInfo->sinfo[1].errormsg
608*7c478bd9Sstevel@tonic-gate 					= strdup(errmsg);
609*7c478bd9Sstevel@tonic-gate 			serverInfo->sinfo[1].info_status
610*7c478bd9Sstevel@tonic-gate 						= INFO_STATUS_ERROR;
611*7c478bd9Sstevel@tonic-gate 			serverInfo->sinfo[1].server_status
612*7c478bd9Sstevel@tonic-gate 						= INFO_SERVER_ERROR;
613*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&serverInfo->mutex[1]);
614*7c478bd9Sstevel@tonic-gate 			if (resultMsg)
615*7c478bd9Sstevel@tonic-gate 				ldap_msgfree(resultMsg);
616*7c478bd9Sstevel@tonic-gate 			ldap_unbind(ld);
617*7c478bd9Sstevel@tonic-gate 			/*
618*7c478bd9Sstevel@tonic-gate 			 * sync sinfo copies in the serverInfo.
619*7c478bd9Sstevel@tonic-gate 			 * protected by mutex
620*7c478bd9Sstevel@tonic-gate 			 */
621*7c478bd9Sstevel@tonic-gate 			sync_current_with_update_copy(serverInfo);
622*7c478bd9Sstevel@tonic-gate 			thr_exit((void *) -1);
623*7c478bd9Sstevel@tonic-gate 			break;
624*7c478bd9Sstevel@tonic-gate 	}
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 	if ((e = ldap_first_entry(ld, resultMsg)) != NULL) {
628*7c478bd9Sstevel@tonic-gate 		/* calculate length of root DSE data */
629*7c478bd9Sstevel@tonic-gate 		for (a = ldap_first_attribute(ld, e, &ber);
630*7c478bd9Sstevel@tonic-gate 			a != NULL;
631*7c478bd9Sstevel@tonic-gate 			a = ldap_next_attribute(ld, e, ber)) {
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 			if ((vals = ldap_get_values(ld, e, a)) != NULL) {
634*7c478bd9Sstevel@tonic-gate 				for (i = 0; vals[i] != NULL; i++) {
635*7c478bd9Sstevel@tonic-gate 					len +=  strlen(a) +
636*7c478bd9Sstevel@tonic-gate 					strlen(vals[i]) +
637*7c478bd9Sstevel@tonic-gate 					strlen(DOORLINESEP) +1;
638*7c478bd9Sstevel@tonic-gate 				}
639*7c478bd9Sstevel@tonic-gate 				ldap_value_free(vals);
640*7c478bd9Sstevel@tonic-gate 			}
641*7c478bd9Sstevel@tonic-gate 			ldap_memfree(a);
642*7c478bd9Sstevel@tonic-gate 		}
643*7c478bd9Sstevel@tonic-gate 		if (ber != NULL)
644*7c478bd9Sstevel@tonic-gate 			ber_free(ber, 0);
645*7c478bd9Sstevel@tonic-gate 		/* copy root DSE data */
646*7c478bd9Sstevel@tonic-gate 		if (len) {
647*7c478bd9Sstevel@tonic-gate 			/* add 1 for the last '\0' */
648*7c478bd9Sstevel@tonic-gate 			rootDSE  = (char *)malloc(len + 1);
649*7c478bd9Sstevel@tonic-gate 			if (rootDSE != NULL) {
650*7c478bd9Sstevel@tonic-gate 				/* make it an empty string first */
651*7c478bd9Sstevel@tonic-gate 				*rootDSE = '\0';
652*7c478bd9Sstevel@tonic-gate 				for (a = ldap_first_attribute(ld, e, &ber);
653*7c478bd9Sstevel@tonic-gate 					a != NULL;
654*7c478bd9Sstevel@tonic-gate 					a = ldap_next_attribute(
655*7c478bd9Sstevel@tonic-gate 						ld, e, ber)) {
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 					if ((vals = ldap_get_values(
658*7c478bd9Sstevel@tonic-gate 						ld, e, a)) != NULL) {
659*7c478bd9Sstevel@tonic-gate 						for (i = 0; vals[i] != NULL;
660*7c478bd9Sstevel@tonic-gate 							i++) {
661*7c478bd9Sstevel@tonic-gate 							int len;
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 							len = strlen(a) +
664*7c478bd9Sstevel@tonic-gate 							strlen(vals[i]) +
665*7c478bd9Sstevel@tonic-gate 							strlen(DOORLINESEP) + 2;
666*7c478bd9Sstevel@tonic-gate 							(void) snprintf(
667*7c478bd9Sstevel@tonic-gate 								rootDSE +
668*7c478bd9Sstevel@tonic-gate 								strlen(rootDSE),
669*7c478bd9Sstevel@tonic-gate 								len, "%s=%s%s",
670*7c478bd9Sstevel@tonic-gate 								a, vals[i],
671*7c478bd9Sstevel@tonic-gate 								DOORLINESEP);
672*7c478bd9Sstevel@tonic-gate 						}
673*7c478bd9Sstevel@tonic-gate 						ldap_value_free(vals);
674*7c478bd9Sstevel@tonic-gate 					}
675*7c478bd9Sstevel@tonic-gate 					ldap_memfree(a);
676*7c478bd9Sstevel@tonic-gate 				}
677*7c478bd9Sstevel@tonic-gate 				if (ber != NULL)
678*7c478bd9Sstevel@tonic-gate 					ber_free(ber, 0);
679*7c478bd9Sstevel@tonic-gate 			} else
680*7c478bd9Sstevel@tonic-gate 				len = 0;
681*7c478bd9Sstevel@tonic-gate 		}
682*7c478bd9Sstevel@tonic-gate 	}
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	/* error, if no root DSE data */
685*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&serverInfo->mutex[1]);
686*7c478bd9Sstevel@tonic-gate 	if (len == 0) {
687*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].errormsg =
688*7c478bd9Sstevel@tonic-gate 			strdup(gettext("No root DSE data returned."));
689*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
690*7c478bd9Sstevel@tonic-gate 			logit("getldap_get_rootDSE: %s.\n",
691*7c478bd9Sstevel@tonic-gate 				serverInfo->sinfo[1].errormsg);
692*7c478bd9Sstevel@tonic-gate 		}
693*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].type
694*7c478bd9Sstevel@tonic-gate 				= INFO_RW_UNKNOWN;
695*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].info_status
696*7c478bd9Sstevel@tonic-gate 				= INFO_STATUS_ERROR;
697*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].server_status 	= INFO_SERVER_ERROR;
698*7c478bd9Sstevel@tonic-gate 		exitrc = -1;
699*7c478bd9Sstevel@tonic-gate 	} else {
700*7c478bd9Sstevel@tonic-gate 		/* assume writeable, i.e., can do modify */
701*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].type	= INFO_RW_WRITEABLE;
702*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].server_status
703*7c478bd9Sstevel@tonic-gate 			= INFO_SERVER_UP;
704*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].info_status	= INFO_STATUS_NEW;
705*7c478bd9Sstevel@tonic-gate 		/* remove the last DOORLINESEP */
706*7c478bd9Sstevel@tonic-gate 		*(rootDSE+strlen(rootDSE)-1) = '\0';
707*7c478bd9Sstevel@tonic-gate 		serverInfo->sinfo[1].rootDSE_data = rootDSE;
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 		server_found = 1;
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate 		exitrc = NS_LDAP_SUCCESS;
712*7c478bd9Sstevel@tonic-gate 	}
713*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&serverInfo->mutex[1]);
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	if (resultMsg)
716*7c478bd9Sstevel@tonic-gate 		ldap_msgfree(resultMsg);
717*7c478bd9Sstevel@tonic-gate 	ldap_unbind(ld);
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	/*
720*7c478bd9Sstevel@tonic-gate 	 * sync sinfo copies in the serverInfo.
721*7c478bd9Sstevel@tonic-gate 	 * protected by mutex
722*7c478bd9Sstevel@tonic-gate 	 */
723*7c478bd9Sstevel@tonic-gate 	sync_current_with_update_copy(serverInfo);
724*7c478bd9Sstevel@tonic-gate 	/*
725*7c478bd9Sstevel@tonic-gate 	 * signal that the ldap_cachemgr parent process
726*7c478bd9Sstevel@tonic-gate 	 * should exit now, if it is still waiting
727*7c478bd9Sstevel@tonic-gate 	 */
728*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&sig_mutex);
729*7c478bd9Sstevel@tonic-gate 	if (signal_done == FALSE && server_found) {
730*7c478bd9Sstevel@tonic-gate 		ppid = getppid();
731*7c478bd9Sstevel@tonic-gate 		(void) kill(ppid, SIGUSR1);
732*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
733*7c478bd9Sstevel@tonic-gate 			logit("getldap_get_rootDSE(): "
734*7c478bd9Sstevel@tonic-gate 				"SIGUSR1 signal sent to "
735*7c478bd9Sstevel@tonic-gate 				"parent process(%ld).\n", ppid);
736*7c478bd9Sstevel@tonic-gate 		}
737*7c478bd9Sstevel@tonic-gate 		signal_done = TRUE;
738*7c478bd9Sstevel@tonic-gate 	}
739*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&sig_mutex);
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	thr_exit((void *) exitrc);
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	return ((void *) NULL);
744*7c478bd9Sstevel@tonic-gate }
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate static int
747*7c478bd9Sstevel@tonic-gate getldap_init_serverInfo(server_info_t **head)
748*7c478bd9Sstevel@tonic-gate {
749*7c478bd9Sstevel@tonic-gate 	char		**servers = NULL;
750*7c478bd9Sstevel@tonic-gate 	int		rc = 0, i, exitrc = NS_LDAP_SUCCESS;
751*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *errorp = NULL;
752*7c478bd9Sstevel@tonic-gate 	server_info_t	*info, *tail = NULL;
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	*head = NULL;
755*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
756*7c478bd9Sstevel@tonic-gate 		logit("getldap_init_serverInfo()...\n");
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 	rc = __s_api_getServers(&servers, &errorp);
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
761*7c478bd9Sstevel@tonic-gate 		logit("getldap_init_serverInfo: "
762*7c478bd9Sstevel@tonic-gate 			"__s_api_getServers failed.\n");
763*7c478bd9Sstevel@tonic-gate 		if (errorp)
764*7c478bd9Sstevel@tonic-gate 			__ns_ldap_freeError(&errorp);
765*7c478bd9Sstevel@tonic-gate 		return (-1);
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate 	for (i = 0; servers[i] != NULL; i++) {
768*7c478bd9Sstevel@tonic-gate 		info = (server_info_t *)calloc(1, sizeof (server_info_t));
769*7c478bd9Sstevel@tonic-gate 		if (info == NULL) {
770*7c478bd9Sstevel@tonic-gate 			logit("getldap_init_serverInfo: "
771*7c478bd9Sstevel@tonic-gate 				"not enough memory.\n");
772*7c478bd9Sstevel@tonic-gate 			exitrc = NS_LDAP_MEMORY;
773*7c478bd9Sstevel@tonic-gate 			break;
774*7c478bd9Sstevel@tonic-gate 		}
775*7c478bd9Sstevel@tonic-gate 		if (i == 0) {
776*7c478bd9Sstevel@tonic-gate 			*head = info;
777*7c478bd9Sstevel@tonic-gate 			tail  = info;
778*7c478bd9Sstevel@tonic-gate 		} else {
779*7c478bd9Sstevel@tonic-gate 			tail->next = info;
780*7c478bd9Sstevel@tonic-gate 			tail  = info;
781*7c478bd9Sstevel@tonic-gate 		}
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].addr		= strdup(servers[i]);
784*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].addr == NULL) {
785*7c478bd9Sstevel@tonic-gate 			logit("getldap_init_serverInfo: "
786*7c478bd9Sstevel@tonic-gate 				"not enough memory.\n");
787*7c478bd9Sstevel@tonic-gate 			exitrc = NS_LDAP_MEMORY;
788*7c478bd9Sstevel@tonic-gate 			break;
789*7c478bd9Sstevel@tonic-gate 		}
790*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].addr		= strdup(servers[i]);
791*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].addr == NULL) {
792*7c478bd9Sstevel@tonic-gate 			logit("getldap_init_serverInfo: "
793*7c478bd9Sstevel@tonic-gate 				"not enough memory.\n");
794*7c478bd9Sstevel@tonic-gate 			exitrc = NS_LDAP_MEMORY;
795*7c478bd9Sstevel@tonic-gate 			break;
796*7c478bd9Sstevel@tonic-gate 		}
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].type 		= INFO_RW_UNKNOWN;
799*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].type 		= INFO_RW_UNKNOWN;
800*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].info_status	= INFO_STATUS_UNKNOWN;
801*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].info_status	= INFO_STATUS_UNKNOWN;
802*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].server_status	= INFO_SERVER_UNKNOWN;
803*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].server_status	= INFO_SERVER_UNKNOWN;
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate 		/*
806*7c478bd9Sstevel@tonic-gate 		 * Assume at startup or after the configuration
807*7c478bd9Sstevel@tonic-gate 		 * profile is refreshed, all servers are good.
808*7c478bd9Sstevel@tonic-gate 		 */
809*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].prev_server_status =
810*7c478bd9Sstevel@tonic-gate 					INFO_SERVER_UP;
811*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].prev_server_status =
812*7c478bd9Sstevel@tonic-gate 					INFO_SERVER_UP;
813*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].rootDSE_data	= NULL;
814*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].rootDSE_data	= NULL;
815*7c478bd9Sstevel@tonic-gate 		info->sinfo[0].errormsg 	= NULL;
816*7c478bd9Sstevel@tonic-gate 		info->sinfo[1].errormsg 	= NULL;
817*7c478bd9Sstevel@tonic-gate 		info->next 		= NULL;
818*7c478bd9Sstevel@tonic-gate 	}
819*7c478bd9Sstevel@tonic-gate 	__s_api_free2dArray(servers);
820*7c478bd9Sstevel@tonic-gate 	if (exitrc != NS_LDAP_SUCCESS) {
821*7c478bd9Sstevel@tonic-gate 		if (head && *head) {
822*7c478bd9Sstevel@tonic-gate 			(void) getldap_destroy_serverInfo(*head);
823*7c478bd9Sstevel@tonic-gate 			*head = NULL;
824*7c478bd9Sstevel@tonic-gate 		}
825*7c478bd9Sstevel@tonic-gate 	}
826*7c478bd9Sstevel@tonic-gate 	return (exitrc);
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate static int
830*7c478bd9Sstevel@tonic-gate getldap_destroy_serverInfo(server_info_t *head)
831*7c478bd9Sstevel@tonic-gate {
832*7c478bd9Sstevel@tonic-gate 	server_info_t	*info, *next;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
835*7c478bd9Sstevel@tonic-gate 		logit("getldap_destroy_serverInfo()...\n");
836*7c478bd9Sstevel@tonic-gate 	}
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
839*7c478bd9Sstevel@tonic-gate 		logit("getldap_destroy_serverInfo: "
840*7c478bd9Sstevel@tonic-gate 			"invalid serverInfo list.\n");
841*7c478bd9Sstevel@tonic-gate 		return (-1);
842*7c478bd9Sstevel@tonic-gate 	}
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate 	for (info = head; info; info = next) {
845*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].addr)
846*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[0].addr);
847*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].addr)
848*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[1].addr);
849*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].rootDSE_data)
850*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[0].rootDSE_data);
851*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].rootDSE_data)
852*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[1].rootDSE_data);
853*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].errormsg)
854*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[0].errormsg);
855*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].errormsg)
856*7c478bd9Sstevel@tonic-gate 			free(info->sinfo[1].errormsg);
857*7c478bd9Sstevel@tonic-gate 		next = info->next;
858*7c478bd9Sstevel@tonic-gate 		free(info);
859*7c478bd9Sstevel@tonic-gate 	}
860*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
861*7c478bd9Sstevel@tonic-gate }
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate static int
864*7c478bd9Sstevel@tonic-gate getldap_set_serverInfo(server_info_t *head,
865*7c478bd9Sstevel@tonic-gate 		int reset_bindtime)
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate 	server_info_t	*info;
868*7c478bd9Sstevel@tonic-gate 	int 		atleast1 = 0;
869*7c478bd9Sstevel@tonic-gate 	thread_t	*tid;
870*7c478bd9Sstevel@tonic-gate 	int 		num_threads = 0, i, j;
871*7c478bd9Sstevel@tonic-gate 	void		*status;
872*7c478bd9Sstevel@tonic-gate 	void		**paramVal = NULL;
873*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
876*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_serverInfo()...\n");
877*7c478bd9Sstevel@tonic-gate 	}
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
880*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_serverInfo: "
881*7c478bd9Sstevel@tonic-gate 			"invalid serverInfo list.\n");
882*7c478bd9Sstevel@tonic-gate 		return (-1);
883*7c478bd9Sstevel@tonic-gate 	}
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 	/* Get the bind timeout value */
886*7c478bd9Sstevel@tonic-gate 	if (reset_bindtime == 1) {
887*7c478bd9Sstevel@tonic-gate 		tcptimeout = NS_DEFAULT_BIND_TIMEOUT * 1000;
888*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_getParam(NS_LDAP_BIND_TIME_P,
889*7c478bd9Sstevel@tonic-gate 			&paramVal, &error);
890*7c478bd9Sstevel@tonic-gate 		if (paramVal != NULL && *paramVal != NULL) {
891*7c478bd9Sstevel@tonic-gate 			/* convert to milliseconds */
892*7c478bd9Sstevel@tonic-gate 			tcptimeout = **((int **)paramVal);
893*7c478bd9Sstevel@tonic-gate 			tcptimeout *= 1000;
894*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
895*7c478bd9Sstevel@tonic-gate 		}
896*7c478bd9Sstevel@tonic-gate 		if (error)
897*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 		/* get search timeout value */
900*7c478bd9Sstevel@tonic-gate 		search_timeout = NS_DEFAULT_SEARCH_TIMEOUT;
901*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_getParam(NS_LDAP_SEARCH_TIME_P,
902*7c478bd9Sstevel@tonic-gate 			&paramVal, &error);
903*7c478bd9Sstevel@tonic-gate 		if (paramVal != NULL && *paramVal != NULL) {
904*7c478bd9Sstevel@tonic-gate 			search_timeout = **((int **)paramVal);
905*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
906*7c478bd9Sstevel@tonic-gate 		}
907*7c478bd9Sstevel@tonic-gate 		if (error)
908*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
909*7c478bd9Sstevel@tonic-gate 
910*7c478bd9Sstevel@tonic-gate 	}
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 	for (info = head; info; info = info->next)
913*7c478bd9Sstevel@tonic-gate 		num_threads++;
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	if (num_threads == 0) {
916*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_serverInfo: "
917*7c478bd9Sstevel@tonic-gate 			"empty serverInfo list.\n");
918*7c478bd9Sstevel@tonic-gate 		return (-1);
919*7c478bd9Sstevel@tonic-gate 	}
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	tid = (thread_t *) calloc(1, sizeof (thread_t) * num_threads);
922*7c478bd9Sstevel@tonic-gate 	if (tid == NULL) {
923*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_serverInfo: "
924*7c478bd9Sstevel@tonic-gate 			"No memory to create thread ID list.\n");
925*7c478bd9Sstevel@tonic-gate 		return (-1);
926*7c478bd9Sstevel@tonic-gate 	}
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	for (info = head, i = 0; info; info = info->next, i++) {
929*7c478bd9Sstevel@tonic-gate 		if (thr_create(NULL, 0,
930*7c478bd9Sstevel@tonic-gate 			(void *(*)(void*))getldap_get_rootDSE,
931*7c478bd9Sstevel@tonic-gate 			(void *)info, 0, &tid[i])) {
932*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_serverInfo: "
933*7c478bd9Sstevel@tonic-gate 				"can not create thread %d.\n", i + 1);
934*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < i; j++)
935*7c478bd9Sstevel@tonic-gate 				(void) thr_join(tid[j], NULL, NULL);
936*7c478bd9Sstevel@tonic-gate 			free(tid);
937*7c478bd9Sstevel@tonic-gate 			return (-1);
938*7c478bd9Sstevel@tonic-gate 		}
939*7c478bd9Sstevel@tonic-gate 	}
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_threads; i++) {
942*7c478bd9Sstevel@tonic-gate 		if (thr_join(tid[i], NULL, &status) == 0) {
943*7c478bd9Sstevel@tonic-gate 			if ((int)status == NS_LDAP_SUCCESS)
944*7c478bd9Sstevel@tonic-gate 				atleast1 = 1;
945*7c478bd9Sstevel@tonic-gate 		}
946*7c478bd9Sstevel@tonic-gate 	}
947*7c478bd9Sstevel@tonic-gate 
948*7c478bd9Sstevel@tonic-gate 	free(tid);
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 	if (atleast1)
951*7c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
952*7c478bd9Sstevel@tonic-gate 	else
953*7c478bd9Sstevel@tonic-gate 		return (-1);
954*7c478bd9Sstevel@tonic-gate }
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate /*
957*7c478bd9Sstevel@tonic-gate  * getldap_get_serverInfo processes the GETLDAPSERVER door request passed
958*7c478bd9Sstevel@tonic-gate  * to this function from getldap_serverInfo_op().
959*7c478bd9Sstevel@tonic-gate  * input:
960*7c478bd9Sstevel@tonic-gate  *   a buffer containing an empty string (e.g., input[0]='\0';) or a string
961*7c478bd9Sstevel@tonic-gate  *   as the "input" in printf(input, "%s%s%s", req, DOORLINESEP, addr);
962*7c478bd9Sstevel@tonic-gate  *   where addr is the address of a server and
963*7c478bd9Sstevel@tonic-gate  *   req is one of the following:
964*7c478bd9Sstevel@tonic-gate  *   NS_CACHE_NEW:    send a new server address, addr is ignored.
965*7c478bd9Sstevel@tonic-gate  *   NS_CACHE_NORESP: send the next one, remove addr from list.
966*7c478bd9Sstevel@tonic-gate  *   NS_CACHE_NEXT:   send the next one, keep addr on list.
967*7c478bd9Sstevel@tonic-gate  *   NS_CACHE_WRITE:  send a non-replica server, if possible, if not, same
968*7c478bd9Sstevel@tonic-gate  *                    as NS_CACHE_NEXT.
969*7c478bd9Sstevel@tonic-gate  * output:
970*7c478bd9Sstevel@tonic-gate  *   a buffer containing server info in the following format:
971*7c478bd9Sstevel@tonic-gate  *   serveraddress DOORLINESEP [ attr=value [DOORLINESEP attr=value ]...]
972*7c478bd9Sstevel@tonic-gate  *   for example: ( here | used as DOORLINESEP for visual purposes)
973*7c478bd9Sstevel@tonic-gate  *   1.2.3.4|supportedControl=1.1.1.1|supportedSASLmechanisms=EXTERNAL
974*7c478bd9Sstevel@tonic-gate  *   NOTE: caller should free this buffer when done using it
975*7c478bd9Sstevel@tonic-gate  */
976*7c478bd9Sstevel@tonic-gate static int
977*7c478bd9Sstevel@tonic-gate getldap_get_serverInfo(server_info_t *head, char *input,
978*7c478bd9Sstevel@tonic-gate 		char **output, int *svr_removed)
979*7c478bd9Sstevel@tonic-gate {
980*7c478bd9Sstevel@tonic-gate 	server_info_t	*info 	= NULL;
981*7c478bd9Sstevel@tonic-gate 	server_info_t	*server	= NULL;
982*7c478bd9Sstevel@tonic-gate 	char 		*addr	= NULL;
983*7c478bd9Sstevel@tonic-gate 	char 		*req	= NULL;
984*7c478bd9Sstevel@tonic-gate 	char 		req_new[] = NS_CACHE_NEW;
985*7c478bd9Sstevel@tonic-gate 	int		matched = FALSE, len;
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
988*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_serverInfo()...\n");
989*7c478bd9Sstevel@tonic-gate 	}
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 	if (input == NULL || output == NULL) {
992*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_serverInfo: "
993*7c478bd9Sstevel@tonic-gate 			"No input or output buffer.\n");
994*7c478bd9Sstevel@tonic-gate 		return (-1);
995*7c478bd9Sstevel@tonic-gate 	}
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	*output = NULL;
998*7c478bd9Sstevel@tonic-gate 	*svr_removed = FALSE;
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
1001*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_serverInfo: "
1002*7c478bd9Sstevel@tonic-gate 			"invalid serverInfo list.\n");
1003*7c478bd9Sstevel@tonic-gate 		return (-1);
1004*7c478bd9Sstevel@tonic-gate 	}
1005*7c478bd9Sstevel@tonic-gate 	/*
1006*7c478bd9Sstevel@tonic-gate 	 * parse the input string to get req and addr,
1007*7c478bd9Sstevel@tonic-gate 	 * if input is empty, i.e., input[0] == '\0',
1008*7c478bd9Sstevel@tonic-gate 	 * treat it as an NS_CACHE_NEW request
1009*7c478bd9Sstevel@tonic-gate 	 */
1010*7c478bd9Sstevel@tonic-gate 	req = req_new;
1011*7c478bd9Sstevel@tonic-gate 	if (input[0] != '\0') {
1012*7c478bd9Sstevel@tonic-gate 		req = input;
1013*7c478bd9Sstevel@tonic-gate 		input[strlen(NS_CACHE_NEW)] = '\0';
1014*7c478bd9Sstevel@tonic-gate 		addr = input + strlen(DOORLINESEP) + strlen(NS_CACHE_NEW);
1015*7c478bd9Sstevel@tonic-gate 	}
1016*7c478bd9Sstevel@tonic-gate 	/*
1017*7c478bd9Sstevel@tonic-gate 	 * if NS_CACHE_NEW,
1018*7c478bd9Sstevel@tonic-gate 	 * or the server info is new,
1019*7c478bd9Sstevel@tonic-gate 	 * starts from the
1020*7c478bd9Sstevel@tonic-gate 	 * beginning of the list
1021*7c478bd9Sstevel@tonic-gate 	 */
1022*7c478bd9Sstevel@tonic-gate 	if ((strcmp(req, NS_CACHE_NEW) == 0) ||
1023*7c478bd9Sstevel@tonic-gate 		(head->sinfo[0].info_status == INFO_STATUS_NEW))
1024*7c478bd9Sstevel@tonic-gate 		matched = TRUE;
1025*7c478bd9Sstevel@tonic-gate 	for (info = head; info; info = info->next) {
1026*7c478bd9Sstevel@tonic-gate 		/*
1027*7c478bd9Sstevel@tonic-gate 		 * make sure the server info stays the same
1028*7c478bd9Sstevel@tonic-gate 		 * while the data is being processed
1029*7c478bd9Sstevel@tonic-gate 		 */
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 		/*
1032*7c478bd9Sstevel@tonic-gate 		 * This function is called to get server info list
1033*7c478bd9Sstevel@tonic-gate 		 * and pass it back to door call clients.
1034*7c478bd9Sstevel@tonic-gate 		 * Access the current copy (sinfo[0]) to get such
1035*7c478bd9Sstevel@tonic-gate 		 * information
1036*7c478bd9Sstevel@tonic-gate 		 */
1037*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info->mutex[0]);
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 		if (matched == FALSE &&
1040*7c478bd9Sstevel@tonic-gate 			strcmp(info->sinfo[0].addr, addr) == 0) {
1041*7c478bd9Sstevel@tonic-gate 			matched = TRUE;
1042*7c478bd9Sstevel@tonic-gate 			if (strcmp(req, NS_CACHE_NORESP) == 0) {
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate 				/*
1045*7c478bd9Sstevel@tonic-gate 				 * if the server has already been removed,
1046*7c478bd9Sstevel@tonic-gate 				 * don't bother
1047*7c478bd9Sstevel@tonic-gate 				 */
1048*7c478bd9Sstevel@tonic-gate 				if (info->sinfo[0].server_status ==
1049*7c478bd9Sstevel@tonic-gate 						INFO_SERVER_REMOVED) {
1050*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&info->mutex[0]);
1051*7c478bd9Sstevel@tonic-gate 					continue;
1052*7c478bd9Sstevel@tonic-gate 				}
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 				/*
1055*7c478bd9Sstevel@tonic-gate 				 * if the information is new,
1056*7c478bd9Sstevel@tonic-gate 				 * give this server one more chance
1057*7c478bd9Sstevel@tonic-gate 				 */
1058*7c478bd9Sstevel@tonic-gate 				if (info->sinfo[0].info_status ==
1059*7c478bd9Sstevel@tonic-gate 						INFO_STATUS_NEW &&
1060*7c478bd9Sstevel@tonic-gate 					info->sinfo[0].server_status  ==
1061*7c478bd9Sstevel@tonic-gate 							INFO_SERVER_UP) {
1062*7c478bd9Sstevel@tonic-gate 					server = info;
1063*7c478bd9Sstevel@tonic-gate 					break;
1064*7c478bd9Sstevel@tonic-gate 				} else {
1065*7c478bd9Sstevel@tonic-gate 					/*
1066*7c478bd9Sstevel@tonic-gate 					 * it is recommended that
1067*7c478bd9Sstevel@tonic-gate 					 * before removing the
1068*7c478bd9Sstevel@tonic-gate 					 * server from the list,
1069*7c478bd9Sstevel@tonic-gate 					 * the server should be
1070*7c478bd9Sstevel@tonic-gate 					 * contacted one more time
1071*7c478bd9Sstevel@tonic-gate 					 * to make sure that it is
1072*7c478bd9Sstevel@tonic-gate 					 * really unavailable.
1073*7c478bd9Sstevel@tonic-gate 					 * For now, just trust the client
1074*7c478bd9Sstevel@tonic-gate 					 * (i.e., the sldap library)
1075*7c478bd9Sstevel@tonic-gate 					 * that it knows what it is
1076*7c478bd9Sstevel@tonic-gate 					 * doing and would not try
1077*7c478bd9Sstevel@tonic-gate 					 * to mess up the server
1078*7c478bd9Sstevel@tonic-gate 					 * list.
1079*7c478bd9Sstevel@tonic-gate 					 */
1080*7c478bd9Sstevel@tonic-gate 					info->sinfo[0].prev_server_status =
1081*7c478bd9Sstevel@tonic-gate 						info->sinfo[0].server_status;
1082*7c478bd9Sstevel@tonic-gate 					info->sinfo[0].server_status  =
1083*7c478bd9Sstevel@tonic-gate 						INFO_SERVER_REMOVED;
1084*7c478bd9Sstevel@tonic-gate 					/*
1085*7c478bd9Sstevel@tonic-gate 					 * make sure this will be seen
1086*7c478bd9Sstevel@tonic-gate 					 * if a user query the server
1087*7c478bd9Sstevel@tonic-gate 					 * status via the ldap_cachemgr's
1088*7c478bd9Sstevel@tonic-gate 					 * -g option
1089*7c478bd9Sstevel@tonic-gate 					 */
1090*7c478bd9Sstevel@tonic-gate 					info->sinfo[1].server_status  =
1091*7c478bd9Sstevel@tonic-gate 						INFO_SERVER_REMOVED;
1092*7c478bd9Sstevel@tonic-gate 					*svr_removed = TRUE;
1093*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&info->mutex[0]);
1094*7c478bd9Sstevel@tonic-gate 					continue;
1095*7c478bd9Sstevel@tonic-gate 				}
1096*7c478bd9Sstevel@tonic-gate 			} else {
1097*7c478bd9Sstevel@tonic-gate 				/*
1098*7c478bd9Sstevel@tonic-gate 				 * req == NS_CACHE_NEXT or NS_CACHE_WRITE
1099*7c478bd9Sstevel@tonic-gate 				 */
1100*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&info->mutex[0]);
1101*7c478bd9Sstevel@tonic-gate 				continue;
1102*7c478bd9Sstevel@tonic-gate 			}
1103*7c478bd9Sstevel@tonic-gate 		}
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 		if (matched) {
1106*7c478bd9Sstevel@tonic-gate 			if (strcmp(req, NS_CACHE_WRITE) == 0) {
1107*7c478bd9Sstevel@tonic-gate 				if (info->sinfo[0].type ==
1108*7c478bd9Sstevel@tonic-gate 					INFO_RW_WRITEABLE &&
1109*7c478bd9Sstevel@tonic-gate 					info->sinfo[0].server_status  ==
1110*7c478bd9Sstevel@tonic-gate 						INFO_SERVER_UP) {
1111*7c478bd9Sstevel@tonic-gate 					server = info;
1112*7c478bd9Sstevel@tonic-gate 					break;
1113*7c478bd9Sstevel@tonic-gate 				}
1114*7c478bd9Sstevel@tonic-gate 			} else if (info->sinfo[0].server_status ==
1115*7c478bd9Sstevel@tonic-gate 					INFO_SERVER_UP) {
1116*7c478bd9Sstevel@tonic-gate 				server = info;
1117*7c478bd9Sstevel@tonic-gate 				break;
1118*7c478bd9Sstevel@tonic-gate 			}
1119*7c478bd9Sstevel@tonic-gate 		}
1120*7c478bd9Sstevel@tonic-gate 
1121*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info->mutex[0]);
1122*7c478bd9Sstevel@tonic-gate 	}
1123*7c478bd9Sstevel@tonic-gate 
1124*7c478bd9Sstevel@tonic-gate 	if (server) {
1125*7c478bd9Sstevel@tonic-gate 		len = strlen(server->sinfo[0].addr) +
1126*7c478bd9Sstevel@tonic-gate 			strlen(server->sinfo[0].rootDSE_data) +
1127*7c478bd9Sstevel@tonic-gate 			strlen(DOORLINESEP) + 1;
1128*7c478bd9Sstevel@tonic-gate 		*output = (char *)malloc(len);
1129*7c478bd9Sstevel@tonic-gate 		if (*output == NULL) {
1130*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&info->mutex[0]);
1131*7c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
1132*7c478bd9Sstevel@tonic-gate 		}
1133*7c478bd9Sstevel@tonic-gate 		(void) snprintf(*output, len, "%s%s%s",
1134*7c478bd9Sstevel@tonic-gate 			server->sinfo[0].addr, DOORLINESEP,
1135*7c478bd9Sstevel@tonic-gate 			server->sinfo[0].rootDSE_data);
1136*7c478bd9Sstevel@tonic-gate 		server->sinfo[0].info_status = INFO_STATUS_OLD;
1137*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info->mutex[0]);
1138*7c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
1139*7c478bd9Sstevel@tonic-gate 	}
1140*7c478bd9Sstevel@tonic-gate 	else
1141*7c478bd9Sstevel@tonic-gate 		return (-99);
1142*7c478bd9Sstevel@tonic-gate }
1143*7c478bd9Sstevel@tonic-gate 
1144*7c478bd9Sstevel@tonic-gate /*
1145*7c478bd9Sstevel@tonic-gate  * Format previous and next refresh time
1146*7c478bd9Sstevel@tonic-gate  */
1147*7c478bd9Sstevel@tonic-gate static int
1148*7c478bd9Sstevel@tonic-gate getldap_format_refresh_time(char **output, time_t *prev, time_t *next)
1149*7c478bd9Sstevel@tonic-gate {
1150*7c478bd9Sstevel@tonic-gate #define	TIME_FORMAT	"%Y/%m/%d %H:%M:%S"
1151*7c478bd9Sstevel@tonic-gate #define	TIME_HEADER1	"  Previous refresh time: "
1152*7c478bd9Sstevel@tonic-gate #define	TIME_HEADER2	"  Next refresh time:     "
1153*7c478bd9Sstevel@tonic-gate 	int		hdr1_len = strlen(gettext(TIME_HEADER1));
1154*7c478bd9Sstevel@tonic-gate 	int		hdr2_len = strlen(gettext(TIME_HEADER2));
1155*7c478bd9Sstevel@tonic-gate 	struct	tm 	tm;
1156*7c478bd9Sstevel@tonic-gate 	char		nbuf[256];
1157*7c478bd9Sstevel@tonic-gate 	char		pbuf[256];
1158*7c478bd9Sstevel@tonic-gate 	int		len;
1159*7c478bd9Sstevel@tonic-gate 
1160*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1161*7c478bd9Sstevel@tonic-gate 		logit("getldap_format_refresh_time()...\n");
1162*7c478bd9Sstevel@tonic-gate 	}
1163*7c478bd9Sstevel@tonic-gate 
1164*7c478bd9Sstevel@tonic-gate 	*output = NULL;
1165*7c478bd9Sstevel@tonic-gate 
1166*7c478bd9Sstevel@tonic-gate 	/* format the time of previous refresh  */
1167*7c478bd9Sstevel@tonic-gate 	if (*prev != 0) {
1168*7c478bd9Sstevel@tonic-gate 		(void) localtime_r(prev, &tm);
1169*7c478bd9Sstevel@tonic-gate 		(void) strftime(pbuf, sizeof (pbuf) - 1, TIME_FORMAT, &tm);
1170*7c478bd9Sstevel@tonic-gate 	} else {
1171*7c478bd9Sstevel@tonic-gate 		(void) strcpy(pbuf, gettext("NOT DONE"));
1172*7c478bd9Sstevel@tonic-gate 	}
1173*7c478bd9Sstevel@tonic-gate 
1174*7c478bd9Sstevel@tonic-gate 	/* format the time of next refresh  */
1175*7c478bd9Sstevel@tonic-gate 	if (*next != 0) {
1176*7c478bd9Sstevel@tonic-gate 		(void) localtime_r(next, &tm);
1177*7c478bd9Sstevel@tonic-gate 		(void) strftime(nbuf, sizeof (nbuf) - 1, TIME_FORMAT, &tm);
1178*7c478bd9Sstevel@tonic-gate 	} else {
1179*7c478bd9Sstevel@tonic-gate 		(void) strcpy(nbuf, gettext("NOT SET"));
1180*7c478bd9Sstevel@tonic-gate 	}
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate 	len = hdr1_len + hdr2_len + strlen(nbuf) +
1183*7c478bd9Sstevel@tonic-gate 			strlen(pbuf) + 2 * strlen(DOORLINESEP) + 1;
1184*7c478bd9Sstevel@tonic-gate 
1185*7c478bd9Sstevel@tonic-gate 	*output = malloc(len);
1186*7c478bd9Sstevel@tonic-gate 	if (*output == NULL)
1187*7c478bd9Sstevel@tonic-gate 		return (-1);
1188*7c478bd9Sstevel@tonic-gate 
1189*7c478bd9Sstevel@tonic-gate 	(void) snprintf(*output, len, "%s%s%s%s%s%s",
1190*7c478bd9Sstevel@tonic-gate 		gettext(TIME_HEADER1), pbuf, DOORLINESEP,
1191*7c478bd9Sstevel@tonic-gate 		gettext(TIME_HEADER2), nbuf, DOORLINESEP);
1192*7c478bd9Sstevel@tonic-gate 
1193*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1194*7c478bd9Sstevel@tonic-gate }
1195*7c478bd9Sstevel@tonic-gate 
1196*7c478bd9Sstevel@tonic-gate /*
1197*7c478bd9Sstevel@tonic-gate  * getldap_get_server_stat processes the GETSTAT request passed
1198*7c478bd9Sstevel@tonic-gate  * to this function from getldap_serverInfo_op().
1199*7c478bd9Sstevel@tonic-gate  * output:
1200*7c478bd9Sstevel@tonic-gate  *   a buffer containing info for all the servers.
1201*7c478bd9Sstevel@tonic-gate  *   For each server, the data is in the following format:
1202*7c478bd9Sstevel@tonic-gate  *   server: server address or name, status: unknown|up|down|removed DOORLINESEP
1203*7c478bd9Sstevel@tonic-gate  *   for example: ( here | used as DOORLINESEP for visual purposes)
1204*7c478bd9Sstevel@tonic-gate  *   server: 1.2.3.4, status: down|server: 2.2.2.2, status: up|
1205*7c478bd9Sstevel@tonic-gate  *   NOTE: caller should free this buffer when done using it
1206*7c478bd9Sstevel@tonic-gate  */
1207*7c478bd9Sstevel@tonic-gate static int
1208*7c478bd9Sstevel@tonic-gate getldap_get_server_stat(server_info_t *head, char **output,
1209*7c478bd9Sstevel@tonic-gate 		time_t *prev, time_t *next)
1210*7c478bd9Sstevel@tonic-gate {
1211*7c478bd9Sstevel@tonic-gate #define	S_HEADER	"Server information: "
1212*7c478bd9Sstevel@tonic-gate #define	S_FORMAT	"  server: %s, status: %s%s"
1213*7c478bd9Sstevel@tonic-gate #define	S_ERROR		"    error message: %s%s"
1214*7c478bd9Sstevel@tonic-gate 	server_info_t	*info 	= NULL;
1215*7c478bd9Sstevel@tonic-gate 	int	header_len = strlen(gettext(S_HEADER));
1216*7c478bd9Sstevel@tonic-gate 	int	format_len = strlen(gettext(S_FORMAT));
1217*7c478bd9Sstevel@tonic-gate 	int	error_len = strlen(gettext(S_ERROR));
1218*7c478bd9Sstevel@tonic-gate 	int	len = header_len + strlen(DOORLINESEP);
1219*7c478bd9Sstevel@tonic-gate 	int	len1 = 0;
1220*7c478bd9Sstevel@tonic-gate 	char	*status, *output1 = NULL, *tmpptr;
1221*7c478bd9Sstevel@tonic-gate 
1222*7c478bd9Sstevel@tonic-gate 	*output = NULL;
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1225*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_server_stat()...\n");
1226*7c478bd9Sstevel@tonic-gate 	}
1227*7c478bd9Sstevel@tonic-gate 
1228*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
1229*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_server_stat: "
1230*7c478bd9Sstevel@tonic-gate 			"invalid serverInfo list.\n");
1231*7c478bd9Sstevel@tonic-gate 		return (-1);
1232*7c478bd9Sstevel@tonic-gate 	}
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate 	/* format previous and next refresh time */
1235*7c478bd9Sstevel@tonic-gate 	(void) getldap_format_refresh_time(&output1, prev, next);
1236*7c478bd9Sstevel@tonic-gate 	if (output1 == NULL)
1237*7c478bd9Sstevel@tonic-gate 		return (-1);
1238*7c478bd9Sstevel@tonic-gate 	len += strlen(output1);
1239*7c478bd9Sstevel@tonic-gate 	len1 = len + strlen(DOORLINESEP) + 1;
1240*7c478bd9Sstevel@tonic-gate 
1241*7c478bd9Sstevel@tonic-gate 	*output = (char *)calloc(1, len1);
1242*7c478bd9Sstevel@tonic-gate 	if (*output == NULL) {
1243*7c478bd9Sstevel@tonic-gate 		free(output1);
1244*7c478bd9Sstevel@tonic-gate 		return (-1);
1245*7c478bd9Sstevel@tonic-gate 	}
1246*7c478bd9Sstevel@tonic-gate 
1247*7c478bd9Sstevel@tonic-gate 	/* insert header string and refresh time info */
1248*7c478bd9Sstevel@tonic-gate 	(void) snprintf(*output, len1, "%s%s%s",
1249*7c478bd9Sstevel@tonic-gate 		gettext(S_HEADER), DOORLINESEP, output1);
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate 	for (info = head; info; info = info->next) {
1252*7c478bd9Sstevel@tonic-gate 
1253*7c478bd9Sstevel@tonic-gate 		/*
1254*7c478bd9Sstevel@tonic-gate 		 * make sure the server info stays the same
1255*7c478bd9Sstevel@tonic-gate 		 * while the data is being processed
1256*7c478bd9Sstevel@tonic-gate 		 */
1257*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info->mutex[1]);
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 		/*
1260*7c478bd9Sstevel@tonic-gate 		 * When the updating process is under way(getldap_get_rootDSE)
1261*7c478bd9Sstevel@tonic-gate 		 * the update copy(sinfo[1] is the latest copy.
1262*7c478bd9Sstevel@tonic-gate 		 * When the updating process
1263*7c478bd9Sstevel@tonic-gate 		 * is done, the current copy (sinfo[0]) has the latest status,
1264*7c478bd9Sstevel@tonic-gate 		 * which is still identical to the update copy.
1265*7c478bd9Sstevel@tonic-gate 		 * So update copy has the latest status.
1266*7c478bd9Sstevel@tonic-gate 		 * Use the update copy(sinfo[1]) to show status
1267*7c478bd9Sstevel@tonic-gate 		 * (ldap_cachemgr -g).
1268*7c478bd9Sstevel@tonic-gate 		 *
1269*7c478bd9Sstevel@tonic-gate 		 */
1270*7c478bd9Sstevel@tonic-gate 
1271*7c478bd9Sstevel@tonic-gate 		switch (info->sinfo[1].server_status) {
1272*7c478bd9Sstevel@tonic-gate 		case INFO_SERVER_UNKNOWN:
1273*7c478bd9Sstevel@tonic-gate 			status = gettext("UNKNOWN");
1274*7c478bd9Sstevel@tonic-gate 			break;
1275*7c478bd9Sstevel@tonic-gate 		case INFO_SERVER_CONNECTING:
1276*7c478bd9Sstevel@tonic-gate 			status = gettext("CONNECTING");
1277*7c478bd9Sstevel@tonic-gate 			break;
1278*7c478bd9Sstevel@tonic-gate 		case INFO_SERVER_UP:
1279*7c478bd9Sstevel@tonic-gate 			status = gettext("UP");
1280*7c478bd9Sstevel@tonic-gate 			break;
1281*7c478bd9Sstevel@tonic-gate 		case INFO_SERVER_ERROR:
1282*7c478bd9Sstevel@tonic-gate 			status = gettext("ERROR");
1283*7c478bd9Sstevel@tonic-gate 			break;
1284*7c478bd9Sstevel@tonic-gate 		case INFO_SERVER_REMOVED:
1285*7c478bd9Sstevel@tonic-gate 			status = gettext("REMOVED");
1286*7c478bd9Sstevel@tonic-gate 			break;
1287*7c478bd9Sstevel@tonic-gate 		}
1288*7c478bd9Sstevel@tonic-gate 
1289*7c478bd9Sstevel@tonic-gate 		len += format_len + strlen(status) +
1290*7c478bd9Sstevel@tonic-gate 			strlen(info->sinfo[1].addr) +
1291*7c478bd9Sstevel@tonic-gate 			strlen(DOORLINESEP);
1292*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].errormsg != NULL)
1293*7c478bd9Sstevel@tonic-gate 			len += error_len +
1294*7c478bd9Sstevel@tonic-gate 				strlen(info->sinfo[1].errormsg) +
1295*7c478bd9Sstevel@tonic-gate 				strlen(DOORLINESEP);
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate 		tmpptr = (char *)realloc(*output, len);
1298*7c478bd9Sstevel@tonic-gate 		if (tmpptr == NULL) {
1299*7c478bd9Sstevel@tonic-gate 			free(output1);
1300*7c478bd9Sstevel@tonic-gate 			free(*output);
1301*7c478bd9Sstevel@tonic-gate 			*output = NULL;
1302*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&info->mutex[1]);
1303*7c478bd9Sstevel@tonic-gate 			return (-1);
1304*7c478bd9Sstevel@tonic-gate 		} else
1305*7c478bd9Sstevel@tonic-gate 			*output = tmpptr;
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 		/* insert server IP addr or name and status */
1308*7c478bd9Sstevel@tonic-gate 		len1 = len - strlen(*output);
1309*7c478bd9Sstevel@tonic-gate 		(void) snprintf(*output + strlen(*output), len1,
1310*7c478bd9Sstevel@tonic-gate 			gettext(S_FORMAT), info->sinfo[1].addr,
1311*7c478bd9Sstevel@tonic-gate 				status, DOORLINESEP);
1312*7c478bd9Sstevel@tonic-gate 		/* insert error message if any */
1313*7c478bd9Sstevel@tonic-gate 		len1 = len - strlen(*output);
1314*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[1].errormsg != NULL)
1315*7c478bd9Sstevel@tonic-gate 			(void) snprintf(*output + strlen(*output), len1,
1316*7c478bd9Sstevel@tonic-gate 				gettext(S_ERROR),
1317*7c478bd9Sstevel@tonic-gate 					info->sinfo[1].errormsg,
1318*7c478bd9Sstevel@tonic-gate 					DOORLINESEP);
1319*7c478bd9Sstevel@tonic-gate 
1320*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info->mutex[1]);
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 	}
1323*7c478bd9Sstevel@tonic-gate 
1324*7c478bd9Sstevel@tonic-gate 	free(output1);
1325*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1326*7c478bd9Sstevel@tonic-gate }
1327*7c478bd9Sstevel@tonic-gate 
1328*7c478bd9Sstevel@tonic-gate /*
1329*7c478bd9Sstevel@tonic-gate  * Format and return the refresh time statistics
1330*7c478bd9Sstevel@tonic-gate  */
1331*7c478bd9Sstevel@tonic-gate static int
1332*7c478bd9Sstevel@tonic-gate getldap_get_refresh_stat(char **output)
1333*7c478bd9Sstevel@tonic-gate {
1334*7c478bd9Sstevel@tonic-gate #define	R_HEADER0	"Configuration refresh information: "
1335*7c478bd9Sstevel@tonic-gate #define	R_HEADER1	"  Configured to NO REFRESH."
1336*7c478bd9Sstevel@tonic-gate 	int		hdr0_len = strlen(gettext(R_HEADER0));
1337*7c478bd9Sstevel@tonic-gate 	int		hdr1_len = strlen(gettext(R_HEADER1));
1338*7c478bd9Sstevel@tonic-gate 	int		cache_ttl = -1, len = 0;
1339*7c478bd9Sstevel@tonic-gate 	time_t 		expire = 0;
1340*7c478bd9Sstevel@tonic-gate 	void		**paramVal = NULL;
1341*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp = NULL;
1342*7c478bd9Sstevel@tonic-gate 	char		*output1 = NULL;
1343*7c478bd9Sstevel@tonic-gate 
1344*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1345*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_refresh_stat()...\n");
1346*7c478bd9Sstevel@tonic-gate 	}
1347*7c478bd9Sstevel@tonic-gate 
1348*7c478bd9Sstevel@tonic-gate 	*output = NULL;
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate 	/* get configured cache TTL */
1351*7c478bd9Sstevel@tonic-gate 	if ((__ns_ldap_getParam(NS_LDAP_CACHETTL_P,
1352*7c478bd9Sstevel@tonic-gate 		&paramVal, &errorp) == NS_LDAP_SUCCESS) &&
1353*7c478bd9Sstevel@tonic-gate 		paramVal != NULL &&
1354*7c478bd9Sstevel@tonic-gate 		(char *)*paramVal != NULL) {
1355*7c478bd9Sstevel@tonic-gate 			cache_ttl = atol((char *)*paramVal);
1356*7c478bd9Sstevel@tonic-gate 	} else {
1357*7c478bd9Sstevel@tonic-gate 		if (errorp)
1358*7c478bd9Sstevel@tonic-gate 			__ns_ldap_freeError(&errorp);
1359*7c478bd9Sstevel@tonic-gate 	}
1360*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate 	/* cound not get cache TTL */
1363*7c478bd9Sstevel@tonic-gate 	if (cache_ttl == -1)
1364*7c478bd9Sstevel@tonic-gate 		return (-1);
1365*7c478bd9Sstevel@tonic-gate 
1366*7c478bd9Sstevel@tonic-gate 	if (cache_ttl == 0) {
1367*7c478bd9Sstevel@tonic-gate 		len = hdr0_len + hdr1_len +
1368*7c478bd9Sstevel@tonic-gate 			2 * strlen(DOORLINESEP) + 1;
1369*7c478bd9Sstevel@tonic-gate 		*output = malloc(len);
1370*7c478bd9Sstevel@tonic-gate 		if (*output == NULL)
1371*7c478bd9Sstevel@tonic-gate 			return (-1);
1372*7c478bd9Sstevel@tonic-gate 		(void) snprintf(*output, len, "%s%s%s%s",
1373*7c478bd9Sstevel@tonic-gate 			gettext(R_HEADER0), DOORLINESEP,
1374*7c478bd9Sstevel@tonic-gate 			gettext(R_HEADER1), DOORLINESEP);
1375*7c478bd9Sstevel@tonic-gate 	} else {
1376*7c478bd9Sstevel@tonic-gate 
1377*7c478bd9Sstevel@tonic-gate 		/* get configuration expiration time */
1378*7c478bd9Sstevel@tonic-gate 		if ((__ns_ldap_getParam(NS_LDAP_EXP_P,
1379*7c478bd9Sstevel@tonic-gate 			&paramVal, &errorp) == NS_LDAP_SUCCESS) &&
1380*7c478bd9Sstevel@tonic-gate 			paramVal != NULL &&
1381*7c478bd9Sstevel@tonic-gate 			(char *)*paramVal != NULL) {
1382*7c478bd9Sstevel@tonic-gate 				expire = (time_t)atol((char *)*paramVal);
1383*7c478bd9Sstevel@tonic-gate 		} else {
1384*7c478bd9Sstevel@tonic-gate 			if (errorp)
1385*7c478bd9Sstevel@tonic-gate 				__ns_ldap_freeError(&errorp);
1386*7c478bd9Sstevel@tonic-gate 		}
1387*7c478bd9Sstevel@tonic-gate 
1388*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
1389*7c478bd9Sstevel@tonic-gate 
1390*7c478bd9Sstevel@tonic-gate 		/* cound not get expiration time */
1391*7c478bd9Sstevel@tonic-gate 		if (expire == -1)
1392*7c478bd9Sstevel@tonic-gate 			return (-1);
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate 		/* format previous and next refresh time */
1395*7c478bd9Sstevel@tonic-gate 		(void) getldap_format_refresh_time(&output1,
1396*7c478bd9Sstevel@tonic-gate 			&prev_refresh_time, &expire);
1397*7c478bd9Sstevel@tonic-gate 		if (output1 == NULL)
1398*7c478bd9Sstevel@tonic-gate 			return (-1);
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 		len = hdr0_len + strlen(output1) +
1401*7c478bd9Sstevel@tonic-gate 				2 * strlen(DOORLINESEP) + 1;
1402*7c478bd9Sstevel@tonic-gate 		*output = malloc(len);
1403*7c478bd9Sstevel@tonic-gate 		if (*output == NULL) {
1404*7c478bd9Sstevel@tonic-gate 			free(output1);
1405*7c478bd9Sstevel@tonic-gate 			return (-1);
1406*7c478bd9Sstevel@tonic-gate 		}
1407*7c478bd9Sstevel@tonic-gate 		(void) snprintf(*output, len, "%s%s%s%s",
1408*7c478bd9Sstevel@tonic-gate 			gettext(R_HEADER0), DOORLINESEP,
1409*7c478bd9Sstevel@tonic-gate 			output1, DOORLINESEP);
1410*7c478bd9Sstevel@tonic-gate 		free(output1);
1411*7c478bd9Sstevel@tonic-gate 	}
1412*7c478bd9Sstevel@tonic-gate 
1413*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1414*7c478bd9Sstevel@tonic-gate }
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate static int
1417*7c478bd9Sstevel@tonic-gate getldap_get_cacheTTL()
1418*7c478bd9Sstevel@tonic-gate {
1419*7c478bd9Sstevel@tonic-gate 	void		**paramVal = NULL;
1420*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error;
1421*7c478bd9Sstevel@tonic-gate 	int		rc = 0, cachettl;
1422*7c478bd9Sstevel@tonic-gate 
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1425*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_cacheTTL()....\n");
1426*7c478bd9Sstevel@tonic-gate 	}
1427*7c478bd9Sstevel@tonic-gate 
1428*7c478bd9Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_CACHETTL_P,
1429*7c478bd9Sstevel@tonic-gate 		&paramVal, &error)) != NS_LDAP_SUCCESS) {
1430*7c478bd9Sstevel@tonic-gate 		if (error != NULL && error->message != NULL)
1431*7c478bd9Sstevel@tonic-gate 			logit("Error: Unable to get configuration "
1432*7c478bd9Sstevel@tonic-gate 				"refresh TTL: %s\n",
1433*7c478bd9Sstevel@tonic-gate 				error->message);
1434*7c478bd9Sstevel@tonic-gate 		else {
1435*7c478bd9Sstevel@tonic-gate 			char *tmp;
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 			__ns_ldap_err2str(rc, &tmp);
1438*7c478bd9Sstevel@tonic-gate 			logit("Error: Unable to get configuration "
1439*7c478bd9Sstevel@tonic-gate 				"refresh TTL: %s\n", tmp);
1440*7c478bd9Sstevel@tonic-gate 		}
1441*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
1442*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
1443*7c478bd9Sstevel@tonic-gate 		return (-1);
1444*7c478bd9Sstevel@tonic-gate 	}
1445*7c478bd9Sstevel@tonic-gate 	if (paramVal == NULL || (char *)*paramVal == NULL)
1446*7c478bd9Sstevel@tonic-gate 			return (-1);
1447*7c478bd9Sstevel@tonic-gate 	cachettl = atol((char *)*paramVal);
1448*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
1449*7c478bd9Sstevel@tonic-gate 	return (cachettl);
1450*7c478bd9Sstevel@tonic-gate }
1451*7c478bd9Sstevel@tonic-gate 
1452*7c478bd9Sstevel@tonic-gate 
1453*7c478bd9Sstevel@tonic-gate /*
1454*7c478bd9Sstevel@tonic-gate  * This function implements the adaptive server list refresh
1455*7c478bd9Sstevel@tonic-gate  * algorithm used by ldap_cachemgr. The idea is to have the
1456*7c478bd9Sstevel@tonic-gate  * refresh TTL adjust itself between maximum and minimum
1457*7c478bd9Sstevel@tonic-gate  * values. If the server list has been walked three times
1458*7c478bd9Sstevel@tonic-gate  * in a row without errors, the TTL will be doubled. This will
1459*7c478bd9Sstevel@tonic-gate  * be done repeatedly until the maximum value is reached
1460*7c478bd9Sstevel@tonic-gate  * or passed. If passed, the maximum value will be used.
1461*7c478bd9Sstevel@tonic-gate  * If any time a server is found to be down/bad, either
1462*7c478bd9Sstevel@tonic-gate  * after another server list walk or informed by libsldap via
1463*7c478bd9Sstevel@tonic-gate  * the GETLDAPSERVER door calls, the TTL will be set to half
1464*7c478bd9Sstevel@tonic-gate  * of its value, again repeatedly, but no less than the minimum
1465*7c478bd9Sstevel@tonic-gate  * value. Also, at any time, if all the servers on the list
1466*7c478bd9Sstevel@tonic-gate  * are found to be down/bad, the TTL will be set to minimum,
1467*7c478bd9Sstevel@tonic-gate  * so that a "no-server" refresh loop should be entered to try
1468*7c478bd9Sstevel@tonic-gate  * to find a good server as soon as possible. The caller
1469*7c478bd9Sstevel@tonic-gate  * could check the no_gd_server flag for this situation.
1470*7c478bd9Sstevel@tonic-gate  * The maximum and minimum values are initialized when the input
1471*7c478bd9Sstevel@tonic-gate  * refresh_ttl is set to zero, this should occur during
1472*7c478bd9Sstevel@tonic-gate  * ldap_cachemgr startup or every time the server list is
1473*7c478bd9Sstevel@tonic-gate  * recreated after the configuration profile is refreshed
1474*7c478bd9Sstevel@tonic-gate  * from an LDAP server. The maximum is set to the value of
1475*7c478bd9Sstevel@tonic-gate  * the NS_LDAP_CACHETTL parameter (configuration profile
1476*7c478bd9Sstevel@tonic-gate  * refresh TTL), but if it is zero (never refreshed) or can
1477*7c478bd9Sstevel@tonic-gate  * not be retrieved, the maximum is set to the macro
1478*7c478bd9Sstevel@tonic-gate  * REFRESHTTL_MAX (12 hours) defined below. The minimum is
1479*7c478bd9Sstevel@tonic-gate  * set to REFRESHTTL_MIN, which is the TCP connection timeout
1480*7c478bd9Sstevel@tonic-gate  * (tcptimeout) set via the LDAP API ldap_set_option()
1481*7c478bd9Sstevel@tonic-gate  * with the new LDAP_X_OPT_CONNECT_TIMEOUT option plus 10 seconds.
1482*7c478bd9Sstevel@tonic-gate  * This accounts for the maximum possible timeout value for an
1483*7c478bd9Sstevel@tonic-gate  * LDAP TCP connect call.The first refresh TTL, initial value of
1484*7c478bd9Sstevel@tonic-gate  * refresh_ttl, will be set to the smaller of the two,
1485*7c478bd9Sstevel@tonic-gate  * REFRESHTTL_REGULAR (10 minutes) or (REFRESHTTL_MAX + REFRESHTTL_MIN)/2.
1486*7c478bd9Sstevel@tonic-gate  * The idea is to have a low starting value and have the value
1487*7c478bd9Sstevel@tonic-gate  * stay low if the network/server is unstable, but eventually
1488*7c478bd9Sstevel@tonic-gate  * the value will move up to maximum and stay there if the
1489*7c478bd9Sstevel@tonic-gate  * network/server is stable.
1490*7c478bd9Sstevel@tonic-gate  */
1491*7c478bd9Sstevel@tonic-gate static int
1492*7c478bd9Sstevel@tonic-gate getldap_set_refresh_ttl(server_info_t *head, int *refresh_ttl,
1493*7c478bd9Sstevel@tonic-gate 		int *no_gd_server)
1494*7c478bd9Sstevel@tonic-gate {
1495*7c478bd9Sstevel@tonic-gate #define	REFRESHTTL_REGULAR	600
1496*7c478bd9Sstevel@tonic-gate #define	REFRESHTTL_MAX		43200
1497*7c478bd9Sstevel@tonic-gate /* tcptimeout is in milliseconds */
1498*7c478bd9Sstevel@tonic-gate #define	REFRESHTTL_MIN		(tcptimeout/1000) + 10
1499*7c478bd9Sstevel@tonic-gate #define	UP_REFRESH_TTL_NUM	2
1500*7c478bd9Sstevel@tonic-gate 
1501*7c478bd9Sstevel@tonic-gate 	static mutex_t		refresh_mutex;
1502*7c478bd9Sstevel@tonic-gate 	static int		refresh_ttl_max = 0;
1503*7c478bd9Sstevel@tonic-gate 	static int		refresh_ttl_min = 0;
1504*7c478bd9Sstevel@tonic-gate 	static int		num_walked_ok = 0;
1505*7c478bd9Sstevel@tonic-gate 	int			num_servers = 0;
1506*7c478bd9Sstevel@tonic-gate 	int			num_good_servers = 0;
1507*7c478bd9Sstevel@tonic-gate 	int			num_prev_good_servers = 0;
1508*7c478bd9Sstevel@tonic-gate 	server_info_t		*info;
1509*7c478bd9Sstevel@tonic-gate 
1510*7c478bd9Sstevel@tonic-gate 	/* allow one thread at a time */
1511*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&refresh_mutex);
1512*7c478bd9Sstevel@tonic-gate 
1513*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1514*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_refresh_ttl()...\n");
1515*7c478bd9Sstevel@tonic-gate 	}
1516*7c478bd9Sstevel@tonic-gate 
1517*7c478bd9Sstevel@tonic-gate 	if (!head || !refresh_ttl || !no_gd_server) {
1518*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_refresh_ttl: head is "
1519*7c478bd9Sstevel@tonic-gate 			"NULL or refresh_ttl is NULL or "
1520*7c478bd9Sstevel@tonic-gate 			"no_gd_server is NULL");
1521*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&refresh_mutex);
1522*7c478bd9Sstevel@tonic-gate 		return (-1);
1523*7c478bd9Sstevel@tonic-gate 	}
1524*7c478bd9Sstevel@tonic-gate 	*no_gd_server = FALSE;
1525*7c478bd9Sstevel@tonic-gate 
1526*7c478bd9Sstevel@tonic-gate 	/*
1527*7c478bd9Sstevel@tonic-gate 	 * init max. min. TTLs if first time through or a fresh one
1528*7c478bd9Sstevel@tonic-gate 	 */
1529*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1530*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_refresh_ttl:(1) refresh ttl is %d "
1531*7c478bd9Sstevel@tonic-gate 			"seconds\n", *refresh_ttl);
1532*7c478bd9Sstevel@tonic-gate 	}
1533*7c478bd9Sstevel@tonic-gate 	if (*refresh_ttl == 0) {
1534*7c478bd9Sstevel@tonic-gate 		num_walked_ok = 0;
1535*7c478bd9Sstevel@tonic-gate 		/*
1536*7c478bd9Sstevel@tonic-gate 		 * init cache manager server list TTL:
1537*7c478bd9Sstevel@tonic-gate 		 *
1538*7c478bd9Sstevel@tonic-gate 		 * init the min. TTL to
1539*7c478bd9Sstevel@tonic-gate 		 * REFRESHTTL_MIN ( 2*(TCP MSL) + 10 seconds)
1540*7c478bd9Sstevel@tonic-gate 		 */
1541*7c478bd9Sstevel@tonic-gate 		refresh_ttl_min = REFRESHTTL_MIN;
1542*7c478bd9Sstevel@tonic-gate 
1543*7c478bd9Sstevel@tonic-gate 		/*
1544*7c478bd9Sstevel@tonic-gate 		 * try to set the max. TTL to
1545*7c478bd9Sstevel@tonic-gate 		 * configuration refresh TTL (NS_LDAP_CACHETTL),
1546*7c478bd9Sstevel@tonic-gate 		 * if error (-1), or never refreshed (0),
1547*7c478bd9Sstevel@tonic-gate 		 * set it to REFRESHTTL_MAX (12 hours)
1548*7c478bd9Sstevel@tonic-gate 		 */
1549*7c478bd9Sstevel@tonic-gate 		refresh_ttl_max = getldap_get_cacheTTL();
1550*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1551*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(2) refresh ttl is %d "
1552*7c478bd9Sstevel@tonic-gate 				"seconds\n", *refresh_ttl);
1553*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(2) max ttl is %d, "
1554*7c478bd9Sstevel@tonic-gate 				"min ttl is %d seconds\n",
1555*7c478bd9Sstevel@tonic-gate 				refresh_ttl_max, refresh_ttl_min);
1556*7c478bd9Sstevel@tonic-gate 		}
1557*7c478bd9Sstevel@tonic-gate 		if (refresh_ttl_max <= 0)
1558*7c478bd9Sstevel@tonic-gate 			refresh_ttl_max = REFRESHTTL_MAX;
1559*7c478bd9Sstevel@tonic-gate 		else if (refresh_ttl_max < refresh_ttl_min)
1560*7c478bd9Sstevel@tonic-gate 			refresh_ttl_max = refresh_ttl_min;
1561*7c478bd9Sstevel@tonic-gate 
1562*7c478bd9Sstevel@tonic-gate 		/*
1563*7c478bd9Sstevel@tonic-gate 		 * init the first TTL to the smaller of the two:
1564*7c478bd9Sstevel@tonic-gate 		 * REFRESHTTL_REGULAR ( 10 minutes),
1565*7c478bd9Sstevel@tonic-gate 		 * (refresh_ttl_max + refresh_ttl_min)/2
1566*7c478bd9Sstevel@tonic-gate 		 */
1567*7c478bd9Sstevel@tonic-gate 		*refresh_ttl = REFRESHTTL_REGULAR;
1568*7c478bd9Sstevel@tonic-gate 		if (*refresh_ttl > (refresh_ttl_max + refresh_ttl_min) / 2)
1569*7c478bd9Sstevel@tonic-gate 			*refresh_ttl = (refresh_ttl_max + refresh_ttl_min) / 2;
1570*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1571*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(3) refresh ttl is %d "
1572*7c478bd9Sstevel@tonic-gate 				"seconds\n", *refresh_ttl);
1573*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(3) max ttl is %d, "
1574*7c478bd9Sstevel@tonic-gate 				"min ttl is %d seconds\n",
1575*7c478bd9Sstevel@tonic-gate 				refresh_ttl_max, refresh_ttl_min);
1576*7c478bd9Sstevel@tonic-gate 		}
1577*7c478bd9Sstevel@tonic-gate 	}
1578*7c478bd9Sstevel@tonic-gate 
1579*7c478bd9Sstevel@tonic-gate 	/*
1580*7c478bd9Sstevel@tonic-gate 	 * get the servers statistics:
1581*7c478bd9Sstevel@tonic-gate 	 * number of servers on list
1582*7c478bd9Sstevel@tonic-gate 	 * number of good servers on list
1583*7c478bd9Sstevel@tonic-gate 	 * number of pevious good servers on list
1584*7c478bd9Sstevel@tonic-gate 	 */
1585*7c478bd9Sstevel@tonic-gate 	for (info = head; info; info = info->next) {
1586*7c478bd9Sstevel@tonic-gate 		num_servers++;
1587*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info->mutex[0]);
1588*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].server_status  == INFO_SERVER_UP)
1589*7c478bd9Sstevel@tonic-gate 			num_good_servers++;
1590*7c478bd9Sstevel@tonic-gate 		/*
1591*7c478bd9Sstevel@tonic-gate 		 * Server's previous status could be UNKNOWN
1592*7c478bd9Sstevel@tonic-gate 		 * only between the very first and second
1593*7c478bd9Sstevel@tonic-gate 		 * refresh. Treat that UNKNOWN status as up
1594*7c478bd9Sstevel@tonic-gate 		 */
1595*7c478bd9Sstevel@tonic-gate 		if (info->sinfo[0].prev_server_status
1596*7c478bd9Sstevel@tonic-gate 				== INFO_SERVER_UP ||
1597*7c478bd9Sstevel@tonic-gate 			info->sinfo[0].prev_server_status
1598*7c478bd9Sstevel@tonic-gate 				== INFO_SERVER_UNKNOWN)
1599*7c478bd9Sstevel@tonic-gate 			num_prev_good_servers++;
1600*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info->mutex[0]);
1601*7c478bd9Sstevel@tonic-gate 	}
1602*7c478bd9Sstevel@tonic-gate 
1603*7c478bd9Sstevel@tonic-gate 	/*
1604*7c478bd9Sstevel@tonic-gate 	 * if the server list is walked three times in a row
1605*7c478bd9Sstevel@tonic-gate 	 * without problems, double the refresh TTL but no more
1606*7c478bd9Sstevel@tonic-gate 	 * than the max. refresh TTL
1607*7c478bd9Sstevel@tonic-gate 	 */
1608*7c478bd9Sstevel@tonic-gate 	if (num_good_servers == num_servers) {
1609*7c478bd9Sstevel@tonic-gate 		num_walked_ok++;
1610*7c478bd9Sstevel@tonic-gate 		if (num_walked_ok > UP_REFRESH_TTL_NUM)  {
1611*7c478bd9Sstevel@tonic-gate 
1612*7c478bd9Sstevel@tonic-gate 			*refresh_ttl = *refresh_ttl * 2;
1613*7c478bd9Sstevel@tonic-gate 			if (*refresh_ttl > refresh_ttl_max)
1614*7c478bd9Sstevel@tonic-gate 				*refresh_ttl = refresh_ttl_max;
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate 			num_walked_ok = 0;
1617*7c478bd9Sstevel@tonic-gate 		}
1618*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1619*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(4) refresh ttl is %d "
1620*7c478bd9Sstevel@tonic-gate 				"seconds\n", *refresh_ttl);
1621*7c478bd9Sstevel@tonic-gate 		}
1622*7c478bd9Sstevel@tonic-gate 	} else if (num_good_servers == 0) {
1623*7c478bd9Sstevel@tonic-gate 		/*
1624*7c478bd9Sstevel@tonic-gate 		 * if no good server found,
1625*7c478bd9Sstevel@tonic-gate 		 * set refresh TTL to miminum
1626*7c478bd9Sstevel@tonic-gate 		 */
1627*7c478bd9Sstevel@tonic-gate 		*refresh_ttl = refresh_ttl_min;
1628*7c478bd9Sstevel@tonic-gate 		*no_gd_server = TRUE;
1629*7c478bd9Sstevel@tonic-gate 		num_walked_ok = 0;
1630*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1631*7c478bd9Sstevel@tonic-gate 			logit("getldap_set_refresh_ttl:(5) refresh ttl is %d "
1632*7c478bd9Sstevel@tonic-gate 				"seconds\n", *refresh_ttl);
1633*7c478bd9Sstevel@tonic-gate 		}
1634*7c478bd9Sstevel@tonic-gate 	} else if (num_prev_good_servers > num_good_servers) {
1635*7c478bd9Sstevel@tonic-gate 		/*
1636*7c478bd9Sstevel@tonic-gate 		 * if more down/bad servers found,
1637*7c478bd9Sstevel@tonic-gate 		 * decrease the refresh TTL by half
1638*7c478bd9Sstevel@tonic-gate 		 * but no less than the min. refresh TTL
1639*7c478bd9Sstevel@tonic-gate 		 */
1640*7c478bd9Sstevel@tonic-gate 		*refresh_ttl = *refresh_ttl / 2;
1641*7c478bd9Sstevel@tonic-gate 		if (*refresh_ttl < refresh_ttl_min)
1642*7c478bd9Sstevel@tonic-gate 			*refresh_ttl = refresh_ttl_min;
1643*7c478bd9Sstevel@tonic-gate 		num_walked_ok = 0;
1644*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_refresh_ttl:(6) refresh ttl is %d "
1645*7c478bd9Sstevel@tonic-gate 			"seconds\n", *refresh_ttl);
1646*7c478bd9Sstevel@tonic-gate 
1647*7c478bd9Sstevel@tonic-gate 	}
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1650*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_refresh_ttl:(7) refresh ttl is %d seconds\n",
1651*7c478bd9Sstevel@tonic-gate 			*refresh_ttl);
1652*7c478bd9Sstevel@tonic-gate 	}
1653*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&refresh_mutex);
1654*7c478bd9Sstevel@tonic-gate 	return (0);
1655*7c478bd9Sstevel@tonic-gate }
1656*7c478bd9Sstevel@tonic-gate 
1657*7c478bd9Sstevel@tonic-gate static int
1658*7c478bd9Sstevel@tonic-gate getldap_serverInfo_op(info_op_t op, char *input, char **output)
1659*7c478bd9Sstevel@tonic-gate {
1660*7c478bd9Sstevel@tonic-gate 
1661*7c478bd9Sstevel@tonic-gate 	static rwlock_t 	info_lock = DEFAULTRWLOCK;
1662*7c478bd9Sstevel@tonic-gate 	static rwlock_t 	info_lock_old = DEFAULTRWLOCK;
1663*7c478bd9Sstevel@tonic-gate 	static mutex_t		info_mutex;
1664*7c478bd9Sstevel@tonic-gate 	static cond_t		info_cond;
1665*7c478bd9Sstevel@tonic-gate 	static int		creating = FALSE;
1666*7c478bd9Sstevel@tonic-gate 	static int		refresh_ttl = 0;
1667*7c478bd9Sstevel@tonic-gate 	static int		sec_to_refresh = 0;
1668*7c478bd9Sstevel@tonic-gate 	static int		in_no_server_mode = FALSE;
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	static server_info_t 	*serverInfo = NULL;
1671*7c478bd9Sstevel@tonic-gate 	static server_info_t 	*serverInfo_old = NULL;
1672*7c478bd9Sstevel@tonic-gate 	server_info_t 		*serverInfo_1;
1673*7c478bd9Sstevel@tonic-gate 	int 			is_creating;
1674*7c478bd9Sstevel@tonic-gate 	int 			err, no_server_good = FALSE;
1675*7c478bd9Sstevel@tonic-gate 	int 			server_removed = FALSE;
1676*7c478bd9Sstevel@tonic-gate 	static struct timespec	timeout;
1677*7c478bd9Sstevel@tonic-gate 	struct timespec		new_timeout;
1678*7c478bd9Sstevel@tonic-gate 	struct timeval		tp;
1679*7c478bd9Sstevel@tonic-gate 	static time_t		prev_refresh = 0, next_refresh = 0;
1680*7c478bd9Sstevel@tonic-gate 
1681*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
1682*7c478bd9Sstevel@tonic-gate 		logit("getldap_serverInfo_op()...\n");
1683*7c478bd9Sstevel@tonic-gate 	}
1684*7c478bd9Sstevel@tonic-gate 	switch (op) {
1685*7c478bd9Sstevel@tonic-gate 	case INFO_OP_CREATE:
1686*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
1687*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_CREATE...\n");
1688*7c478bd9Sstevel@tonic-gate 		}
1689*7c478bd9Sstevel@tonic-gate 
1690*7c478bd9Sstevel@tonic-gate 		/*
1691*7c478bd9Sstevel@tonic-gate 		 * indicate that the server info is being
1692*7c478bd9Sstevel@tonic-gate 		 * (re)created, so that the refresh thread
1693*7c478bd9Sstevel@tonic-gate 		 * will not refresh the info list right
1694*7c478bd9Sstevel@tonic-gate 		 * after the list got (re)created
1695*7c478bd9Sstevel@tonic-gate 		 */
1696*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info_mutex);
1697*7c478bd9Sstevel@tonic-gate 		is_creating = creating;
1698*7c478bd9Sstevel@tonic-gate 		creating = TRUE;
1699*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info_mutex);
1700*7c478bd9Sstevel@tonic-gate 
1701*7c478bd9Sstevel@tonic-gate 		if (is_creating)
1702*7c478bd9Sstevel@tonic-gate 			break;
1703*7c478bd9Sstevel@tonic-gate 		/*
1704*7c478bd9Sstevel@tonic-gate 		 * create an empty info list
1705*7c478bd9Sstevel@tonic-gate 		 */
1706*7c478bd9Sstevel@tonic-gate 		(void) getldap_init_serverInfo(&serverInfo_1);
1707*7c478bd9Sstevel@tonic-gate 		/*
1708*7c478bd9Sstevel@tonic-gate 		 * exit if list not created
1709*7c478bd9Sstevel@tonic-gate 		 */
1710*7c478bd9Sstevel@tonic-gate 		if (serverInfo_1 == NULL) {
1711*7c478bd9Sstevel@tonic-gate 			(void) mutex_lock(&info_mutex);
1712*7c478bd9Sstevel@tonic-gate 			creating = FALSE;
1713*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&info_mutex);
1714*7c478bd9Sstevel@tonic-gate 			break;
1715*7c478bd9Sstevel@tonic-gate 		}
1716*7c478bd9Sstevel@tonic-gate 		/*
1717*7c478bd9Sstevel@tonic-gate 		 * make the new server info available:
1718*7c478bd9Sstevel@tonic-gate 		 * use writer lock here, so that the switch
1719*7c478bd9Sstevel@tonic-gate 		 * is done after all the reader locks have
1720*7c478bd9Sstevel@tonic-gate 		 * been released.
1721*7c478bd9Sstevel@tonic-gate 		 */
1722*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&info_lock);
1723*7c478bd9Sstevel@tonic-gate 		serverInfo = serverInfo_1;
1724*7c478bd9Sstevel@tonic-gate 		/*
1725*7c478bd9Sstevel@tonic-gate 		 * if this is the first time
1726*7c478bd9Sstevel@tonic-gate 		 * the server list is being created,
1727*7c478bd9Sstevel@tonic-gate 		 * (i.e., serverInfo_old is NULL)
1728*7c478bd9Sstevel@tonic-gate 		 * make the old list same as the new
1729*7c478bd9Sstevel@tonic-gate 		 * so the GETSERVER code can do its work
1730*7c478bd9Sstevel@tonic-gate 		 */
1731*7c478bd9Sstevel@tonic-gate 		if (serverInfo_old == NULL)
1732*7c478bd9Sstevel@tonic-gate 			serverInfo_old = serverInfo_1;
1733*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock);
1734*7c478bd9Sstevel@tonic-gate 
1735*7c478bd9Sstevel@tonic-gate 		/*
1736*7c478bd9Sstevel@tonic-gate 		 * fill the new info list
1737*7c478bd9Sstevel@tonic-gate 		 */
1738*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&info_lock);
1739*7c478bd9Sstevel@tonic-gate 		/* reset bind time (tcptimeout) */
1740*7c478bd9Sstevel@tonic-gate 		(void) getldap_set_serverInfo(serverInfo, 1);
1741*7c478bd9Sstevel@tonic-gate 
1742*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info_mutex);
1743*7c478bd9Sstevel@tonic-gate 		/*
1744*7c478bd9Sstevel@tonic-gate 		 * set cache manager server list TTL,
1745*7c478bd9Sstevel@tonic-gate 		 * set refresh_ttl to zero to indicate a fresh one
1746*7c478bd9Sstevel@tonic-gate 		 */
1747*7c478bd9Sstevel@tonic-gate 		refresh_ttl = 0;
1748*7c478bd9Sstevel@tonic-gate 		(void) getldap_set_refresh_ttl(serverInfo,
1749*7c478bd9Sstevel@tonic-gate 				&refresh_ttl, &no_server_good);
1750*7c478bd9Sstevel@tonic-gate 		sec_to_refresh = refresh_ttl;
1751*7c478bd9Sstevel@tonic-gate 
1752*7c478bd9Sstevel@tonic-gate 		/* statistics: previous refresh time */
1753*7c478bd9Sstevel@tonic-gate 		if (gettimeofday(&tp, NULL) == 0)
1754*7c478bd9Sstevel@tonic-gate 			prev_refresh = tp.tv_sec;
1755*7c478bd9Sstevel@tonic-gate 
1756*7c478bd9Sstevel@tonic-gate 		creating = FALSE;
1757*7c478bd9Sstevel@tonic-gate 
1758*7c478bd9Sstevel@tonic-gate 		/*
1759*7c478bd9Sstevel@tonic-gate 		 * if no server found or available,
1760*7c478bd9Sstevel@tonic-gate 		 * tell the server info refresh thread
1761*7c478bd9Sstevel@tonic-gate 		 * to start the "no-server" refresh loop
1762*7c478bd9Sstevel@tonic-gate 		 * otherwise reset the in_no_server_mode flag
1763*7c478bd9Sstevel@tonic-gate 		 */
1764*7c478bd9Sstevel@tonic-gate 		if (no_server_good) {
1765*7c478bd9Sstevel@tonic-gate 			sec_to_refresh = 0;
1766*7c478bd9Sstevel@tonic-gate 			in_no_server_mode = TRUE;
1767*7c478bd9Sstevel@tonic-gate 		} else
1768*7c478bd9Sstevel@tonic-gate 			in_no_server_mode = FALSE;
1769*7c478bd9Sstevel@tonic-gate 		/*
1770*7c478bd9Sstevel@tonic-gate 		 * awake the sleeping refresh thread
1771*7c478bd9Sstevel@tonic-gate 		 */
1772*7c478bd9Sstevel@tonic-gate 		(void) cond_signal(&info_cond);
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info_mutex);
1775*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock);
1776*7c478bd9Sstevel@tonic-gate 
1777*7c478bd9Sstevel@tonic-gate 		/*
1778*7c478bd9Sstevel@tonic-gate 		 * delete the old server info
1779*7c478bd9Sstevel@tonic-gate 		 */
1780*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&info_lock_old);
1781*7c478bd9Sstevel@tonic-gate 		if (serverInfo_old != serverInfo)
1782*7c478bd9Sstevel@tonic-gate 			(void) getldap_destroy_serverInfo(serverInfo_old);
1783*7c478bd9Sstevel@tonic-gate 		/*
1784*7c478bd9Sstevel@tonic-gate 		 * serverInfo_old needs to be the same as
1785*7c478bd9Sstevel@tonic-gate 		 * serverinfo now.
1786*7c478bd9Sstevel@tonic-gate 		 * it will be used by GETSERVER processing.
1787*7c478bd9Sstevel@tonic-gate 		 */
1788*7c478bd9Sstevel@tonic-gate 		serverInfo_old = serverInfo;
1789*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock_old);
1790*7c478bd9Sstevel@tonic-gate 		break;
1791*7c478bd9Sstevel@tonic-gate 	case INFO_OP_DELETE:
1792*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
1793*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_DELETE...\n");
1794*7c478bd9Sstevel@tonic-gate 		}
1795*7c478bd9Sstevel@tonic-gate 		/*
1796*7c478bd9Sstevel@tonic-gate 		 * use writer lock here, so that the delete would
1797*7c478bd9Sstevel@tonic-gate 		 * not start until all the reader locks have
1798*7c478bd9Sstevel@tonic-gate 		 * been released.
1799*7c478bd9Sstevel@tonic-gate 		 */
1800*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&info_lock);
1801*7c478bd9Sstevel@tonic-gate 		if (serverInfo)
1802*7c478bd9Sstevel@tonic-gate 			(void) getldap_destroy_serverInfo(serverInfo);
1803*7c478bd9Sstevel@tonic-gate 		serverInfo = NULL;
1804*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock);
1805*7c478bd9Sstevel@tonic-gate 		break;
1806*7c478bd9Sstevel@tonic-gate 	case INFO_OP_REFRESH:
1807*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1808*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_REFRESH...\n");
1809*7c478bd9Sstevel@tonic-gate 		}
1810*7c478bd9Sstevel@tonic-gate 		/*
1811*7c478bd9Sstevel@tonic-gate 		 * if server info is currently being
1812*7c478bd9Sstevel@tonic-gate 		 * (re)created, do nothing
1813*7c478bd9Sstevel@tonic-gate 		 */
1814*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info_mutex);
1815*7c478bd9Sstevel@tonic-gate 		is_creating = creating;
1816*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info_mutex);
1817*7c478bd9Sstevel@tonic-gate 		if (is_creating)
1818*7c478bd9Sstevel@tonic-gate 			break;
1819*7c478bd9Sstevel@tonic-gate 
1820*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&info_lock);
1821*7c478bd9Sstevel@tonic-gate 		if (serverInfo) {
1822*7c478bd9Sstevel@tonic-gate 			/* do not reset bind time (tcptimeout) */
1823*7c478bd9Sstevel@tonic-gate 			(void) getldap_set_serverInfo(serverInfo, 0);
1824*7c478bd9Sstevel@tonic-gate 
1825*7c478bd9Sstevel@tonic-gate 			(void) mutex_lock(&info_mutex);
1826*7c478bd9Sstevel@tonic-gate 
1827*7c478bd9Sstevel@tonic-gate 			/* statistics: previous refresh time */
1828*7c478bd9Sstevel@tonic-gate 			if (gettimeofday(&tp, NULL) == 0)
1829*7c478bd9Sstevel@tonic-gate 				prev_refresh = tp.tv_sec;
1830*7c478bd9Sstevel@tonic-gate 			/*
1831*7c478bd9Sstevel@tonic-gate 			 * set cache manager server list TTL
1832*7c478bd9Sstevel@tonic-gate 			 */
1833*7c478bd9Sstevel@tonic-gate 			(void) getldap_set_refresh_ttl(serverInfo,
1834*7c478bd9Sstevel@tonic-gate 				&refresh_ttl, &no_server_good);
1835*7c478bd9Sstevel@tonic-gate 			/*
1836*7c478bd9Sstevel@tonic-gate 			 * if no good server found,
1837*7c478bd9Sstevel@tonic-gate 			 * tell the server info refresh thread
1838*7c478bd9Sstevel@tonic-gate 			 * to start the "no-server" refresh loop
1839*7c478bd9Sstevel@tonic-gate 			 * otherwise reset the in_no_server_mode flag
1840*7c478bd9Sstevel@tonic-gate 			 */
1841*7c478bd9Sstevel@tonic-gate 			if (no_server_good) {
1842*7c478bd9Sstevel@tonic-gate 				in_no_server_mode = TRUE;
1843*7c478bd9Sstevel@tonic-gate 				sec_to_refresh = 0;
1844*7c478bd9Sstevel@tonic-gate 			} else {
1845*7c478bd9Sstevel@tonic-gate 				in_no_server_mode = FALSE;
1846*7c478bd9Sstevel@tonic-gate 				sec_to_refresh = refresh_ttl;
1847*7c478bd9Sstevel@tonic-gate 			}
1848*7c478bd9Sstevel@tonic-gate 			if (current_admin.debug_level >=
1849*7c478bd9Sstevel@tonic-gate 				DBG_SERVER_LIST_REFRESH) {
1850*7c478bd9Sstevel@tonic-gate 				logit("getldap_serverInfo_op("
1851*7c478bd9Sstevel@tonic-gate 				"INFO_OP_REFRESH):"
1852*7c478bd9Sstevel@tonic-gate 				" seconds refresh: %d second(s)....\n",
1853*7c478bd9Sstevel@tonic-gate 				sec_to_refresh);
1854*7c478bd9Sstevel@tonic-gate 			}
1855*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&info_mutex);
1856*7c478bd9Sstevel@tonic-gate 		}
1857*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock);
1858*7c478bd9Sstevel@tonic-gate 
1859*7c478bd9Sstevel@tonic-gate 		break;
1860*7c478bd9Sstevel@tonic-gate 	case INFO_OP_REFRESH_WAIT:
1861*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) {
1862*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_REFRESH_WAIT...\n");
1863*7c478bd9Sstevel@tonic-gate 		}
1864*7c478bd9Sstevel@tonic-gate 		(void) cond_init(&info_cond, NULL, NULL);
1865*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info_mutex);
1866*7c478bd9Sstevel@tonic-gate 		err = 0;
1867*7c478bd9Sstevel@tonic-gate 		while (err != ETIME) {
1868*7c478bd9Sstevel@tonic-gate 			int sleeptime;
1869*7c478bd9Sstevel@tonic-gate 			/*
1870*7c478bd9Sstevel@tonic-gate 			 * if need to go into the "no-server" refresh
1871*7c478bd9Sstevel@tonic-gate 			 * loop, set timout value to
1872*7c478bd9Sstevel@tonic-gate 			 * REFRESH_DELAY_WHEN_NO_SERVER
1873*7c478bd9Sstevel@tonic-gate 			 */
1874*7c478bd9Sstevel@tonic-gate 			if (sec_to_refresh == 0) {
1875*7c478bd9Sstevel@tonic-gate 				sec_to_refresh = refresh_ttl;
1876*7c478bd9Sstevel@tonic-gate 				timeout.tv_sec = time(NULL) +
1877*7c478bd9Sstevel@tonic-gate 					REFRESH_DELAY_WHEN_NO_SERVER;
1878*7c478bd9Sstevel@tonic-gate 				sleeptime = REFRESH_DELAY_WHEN_NO_SERVER;
1879*7c478bd9Sstevel@tonic-gate 				if (current_admin.debug_level >=
1880*7c478bd9Sstevel@tonic-gate 					DBG_SERVER_LIST_REFRESH) {
1881*7c478bd9Sstevel@tonic-gate 					logit("getldap_serverInfo_op("
1882*7c478bd9Sstevel@tonic-gate 					"INFO_OP_REFRESH_WAIT):"
1883*7c478bd9Sstevel@tonic-gate 					" entering no-server "
1884*7c478bd9Sstevel@tonic-gate 					"refresh loop...\n");
1885*7c478bd9Sstevel@tonic-gate 				}
1886*7c478bd9Sstevel@tonic-gate 			} else {
1887*7c478bd9Sstevel@tonic-gate 				timeout.tv_sec = time(NULL) + sec_to_refresh;
1888*7c478bd9Sstevel@tonic-gate 				sleeptime = sec_to_refresh;
1889*7c478bd9Sstevel@tonic-gate 			}
1890*7c478bd9Sstevel@tonic-gate 			timeout.tv_nsec = 0;
1891*7c478bd9Sstevel@tonic-gate 
1892*7c478bd9Sstevel@tonic-gate 			/* statistics: next refresh time */
1893*7c478bd9Sstevel@tonic-gate 			next_refresh = timeout.tv_sec;
1894*7c478bd9Sstevel@tonic-gate 
1895*7c478bd9Sstevel@tonic-gate 			if (current_admin.debug_level >=
1896*7c478bd9Sstevel@tonic-gate 				DBG_SERVER_LIST_REFRESH) {
1897*7c478bd9Sstevel@tonic-gate 				logit("getldap_serverInfo_op("
1898*7c478bd9Sstevel@tonic-gate 				"INFO_OP_REFRESH_WAIT):"
1899*7c478bd9Sstevel@tonic-gate 				" about to sleep for %d second(s)...\n",
1900*7c478bd9Sstevel@tonic-gate 				sleeptime);
1901*7c478bd9Sstevel@tonic-gate 			}
1902*7c478bd9Sstevel@tonic-gate 			err = cond_timedwait(&info_cond,
1903*7c478bd9Sstevel@tonic-gate 				&info_mutex, &timeout);
1904*7c478bd9Sstevel@tonic-gate 		}
1905*7c478bd9Sstevel@tonic-gate 		(void) cond_destroy(&info_cond);
1906*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info_mutex);
1907*7c478bd9Sstevel@tonic-gate 		break;
1908*7c478bd9Sstevel@tonic-gate 	case INFO_OP_GETSERVER:
1909*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
1910*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_GETSERVER...\n");
1911*7c478bd9Sstevel@tonic-gate 		}
1912*7c478bd9Sstevel@tonic-gate 		*output = NULL;
1913*7c478bd9Sstevel@tonic-gate 		/*
1914*7c478bd9Sstevel@tonic-gate 		 * GETSERVER processing always use
1915*7c478bd9Sstevel@tonic-gate 		 * serverInfo_old to retrieve server infomation.
1916*7c478bd9Sstevel@tonic-gate 		 * serverInfo_old is equal to serverInfo
1917*7c478bd9Sstevel@tonic-gate 		 * most of the time, except when a new
1918*7c478bd9Sstevel@tonic-gate 		 * server list is being created.
1919*7c478bd9Sstevel@tonic-gate 		 * This is why the check for is_creating
1920*7c478bd9Sstevel@tonic-gate 		 * is needed below.
1921*7c478bd9Sstevel@tonic-gate 		 */
1922*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&info_lock_old);
1923*7c478bd9Sstevel@tonic-gate 
1924*7c478bd9Sstevel@tonic-gate 		if (serverInfo_old == NULL) {
1925*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&info_lock_old);
1926*7c478bd9Sstevel@tonic-gate 			break;
1927*7c478bd9Sstevel@tonic-gate 		} else
1928*7c478bd9Sstevel@tonic-gate 			(void) getldap_get_serverInfo(serverInfo_old,
1929*7c478bd9Sstevel@tonic-gate 				input, output, &server_removed);
1930*7c478bd9Sstevel@tonic-gate 
1931*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock_old);
1932*7c478bd9Sstevel@tonic-gate 
1933*7c478bd9Sstevel@tonic-gate 		/*
1934*7c478bd9Sstevel@tonic-gate 		 * if server info is currently being
1935*7c478bd9Sstevel@tonic-gate 		 * (re)created, do nothing
1936*7c478bd9Sstevel@tonic-gate 		 */
1937*7c478bd9Sstevel@tonic-gate 
1938*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&info_mutex);
1939*7c478bd9Sstevel@tonic-gate 		is_creating = creating;
1940*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&info_mutex);
1941*7c478bd9Sstevel@tonic-gate 		if (is_creating)
1942*7c478bd9Sstevel@tonic-gate 			break;
1943*7c478bd9Sstevel@tonic-gate 
1944*7c478bd9Sstevel@tonic-gate 		/*
1945*7c478bd9Sstevel@tonic-gate 		 * set cache manager server list TTL if necessary
1946*7c478bd9Sstevel@tonic-gate 		 */
1947*7c478bd9Sstevel@tonic-gate 		if (*output == NULL || server_removed) {
1948*7c478bd9Sstevel@tonic-gate 			(void) rw_rdlock(&info_lock);
1949*7c478bd9Sstevel@tonic-gate 			(void) mutex_lock(&info_mutex);
1950*7c478bd9Sstevel@tonic-gate 
1951*7c478bd9Sstevel@tonic-gate 			(void) getldap_set_refresh_ttl(serverInfo,
1952*7c478bd9Sstevel@tonic-gate 				&refresh_ttl, &no_server_good);
1953*7c478bd9Sstevel@tonic-gate 
1954*7c478bd9Sstevel@tonic-gate 			/*
1955*7c478bd9Sstevel@tonic-gate 			 * if no good server found, need to go into
1956*7c478bd9Sstevel@tonic-gate 			 * the "no-server" refresh loop
1957*7c478bd9Sstevel@tonic-gate 			 * to find a server as soon as possible
1958*7c478bd9Sstevel@tonic-gate 			 * otherwise reset the in_no_server_mode flag
1959*7c478bd9Sstevel@tonic-gate 			 */
1960*7c478bd9Sstevel@tonic-gate 			if (no_server_good) {
1961*7c478bd9Sstevel@tonic-gate 				/*
1962*7c478bd9Sstevel@tonic-gate 				 * if already in no-server mode,
1963*7c478bd9Sstevel@tonic-gate 				 * don't brother
1964*7c478bd9Sstevel@tonic-gate 				 */
1965*7c478bd9Sstevel@tonic-gate 				if (in_no_server_mode == FALSE) {
1966*7c478bd9Sstevel@tonic-gate 					sec_to_refresh = 0;
1967*7c478bd9Sstevel@tonic-gate 					in_no_server_mode = TRUE;
1968*7c478bd9Sstevel@tonic-gate 					(void) cond_signal(&info_cond);
1969*7c478bd9Sstevel@tonic-gate 				}
1970*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&info_mutex);
1971*7c478bd9Sstevel@tonic-gate 				(void) rw_unlock(&info_lock);
1972*7c478bd9Sstevel@tonic-gate 				break;
1973*7c478bd9Sstevel@tonic-gate 			} else {
1974*7c478bd9Sstevel@tonic-gate 				in_no_server_mode = FALSE;
1975*7c478bd9Sstevel@tonic-gate 				sec_to_refresh = refresh_ttl;
1976*7c478bd9Sstevel@tonic-gate 			}
1977*7c478bd9Sstevel@tonic-gate 			/*
1978*7c478bd9Sstevel@tonic-gate 			 * if the refresh thread will be timed out
1979*7c478bd9Sstevel@tonic-gate 			 * longer than refresh_ttl seconds,
1980*7c478bd9Sstevel@tonic-gate 			 * wake it up to make it wait on the new
1981*7c478bd9Sstevel@tonic-gate 			 * time out value
1982*7c478bd9Sstevel@tonic-gate 			 */
1983*7c478bd9Sstevel@tonic-gate 			new_timeout.tv_sec = time(NULL) + refresh_ttl;
1984*7c478bd9Sstevel@tonic-gate 			if (new_timeout.tv_sec < timeout.tv_sec)
1985*7c478bd9Sstevel@tonic-gate 				(void) cond_signal(&info_cond);
1986*7c478bd9Sstevel@tonic-gate 
1987*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&info_mutex);
1988*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&info_lock);
1989*7c478bd9Sstevel@tonic-gate 		}
1990*7c478bd9Sstevel@tonic-gate 		break;
1991*7c478bd9Sstevel@tonic-gate 	case INFO_OP_GETSTAT:
1992*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_ALL) {
1993*7c478bd9Sstevel@tonic-gate 			logit("operation is INFO_OP_GETSTAT...\n");
1994*7c478bd9Sstevel@tonic-gate 		}
1995*7c478bd9Sstevel@tonic-gate 		*output = NULL;
1996*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&info_lock);
1997*7c478bd9Sstevel@tonic-gate 		if (serverInfo) {
1998*7c478bd9Sstevel@tonic-gate 			(void) getldap_get_server_stat(serverInfo,
1999*7c478bd9Sstevel@tonic-gate 				output, &prev_refresh, &next_refresh);
2000*7c478bd9Sstevel@tonic-gate 		}
2001*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&info_lock);
2002*7c478bd9Sstevel@tonic-gate 		break;
2003*7c478bd9Sstevel@tonic-gate 	default:
2004*7c478bd9Sstevel@tonic-gate 		logit("getldap_serverInfo_op(): "
2005*7c478bd9Sstevel@tonic-gate 			"invalid operation code (%d).\n", op);
2006*7c478bd9Sstevel@tonic-gate 		return (-1);
2007*7c478bd9Sstevel@tonic-gate 		break;
2008*7c478bd9Sstevel@tonic-gate 	}
2009*7c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
2010*7c478bd9Sstevel@tonic-gate }
2011*7c478bd9Sstevel@tonic-gate 
2012*7c478bd9Sstevel@tonic-gate void
2013*7c478bd9Sstevel@tonic-gate getldap_serverInfo_refresh()
2014*7c478bd9Sstevel@tonic-gate {
2015*7c478bd9Sstevel@tonic-gate 	int always = 1;
2016*7c478bd9Sstevel@tonic-gate 
2017*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2018*7c478bd9Sstevel@tonic-gate 		logit("getldap_serverInfo_refresh()...\n");
2019*7c478bd9Sstevel@tonic-gate 	}
2020*7c478bd9Sstevel@tonic-gate 
2021*7c478bd9Sstevel@tonic-gate 	/* create the server info list */
2022*7c478bd9Sstevel@tonic-gate 	(void) getldap_serverInfo_op(INFO_OP_CREATE, NULL, NULL);
2023*7c478bd9Sstevel@tonic-gate 
2024*7c478bd9Sstevel@tonic-gate 	while (always) {
2025*7c478bd9Sstevel@tonic-gate 		/*
2026*7c478bd9Sstevel@tonic-gate 		 * the operation INFO_OP_REFRESH_WAIT
2027*7c478bd9Sstevel@tonic-gate 		 * causes this thread to wait until
2028*7c478bd9Sstevel@tonic-gate 		 * it is time to do refresh,
2029*7c478bd9Sstevel@tonic-gate 		 * see getldap_serverInfo_op() for details
2030*7c478bd9Sstevel@tonic-gate 		 */
2031*7c478bd9Sstevel@tonic-gate 		(void) getldap_serverInfo_op(INFO_OP_REFRESH_WAIT, NULL, NULL);
2032*7c478bd9Sstevel@tonic-gate 		(void) getldap_serverInfo_op(INFO_OP_REFRESH, NULL, NULL);
2033*7c478bd9Sstevel@tonic-gate 	}
2034*7c478bd9Sstevel@tonic-gate }
2035*7c478bd9Sstevel@tonic-gate 
2036*7c478bd9Sstevel@tonic-gate void
2037*7c478bd9Sstevel@tonic-gate getldap_getserver(ldap_return_t *out, ldap_call_t *in)
2038*7c478bd9Sstevel@tonic-gate {
2039*7c478bd9Sstevel@tonic-gate 	char 		*outstr = NULL;
2040*7c478bd9Sstevel@tonic-gate 	char 		req[] = "0";
2041*7c478bd9Sstevel@tonic-gate 
2042*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2043*7c478bd9Sstevel@tonic-gate 		logit("getldap_getserver()...\n");
2044*7c478bd9Sstevel@tonic-gate 	}
2045*7c478bd9Sstevel@tonic-gate 
2046*7c478bd9Sstevel@tonic-gate 	/* assume no server found */
2047*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = -1;
2048*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = NOTFOUND;
2049*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (*out);
2050*7c478bd9Sstevel@tonic-gate 
2051*7c478bd9Sstevel@tonic-gate 	/* make sure the request is valid */
2052*7c478bd9Sstevel@tonic-gate 	req[0] = (in->ldap_u.servername)[0];
2053*7c478bd9Sstevel@tonic-gate 	if ((req[0] != '\0') &&
2054*7c478bd9Sstevel@tonic-gate 		(strcmp(req, NS_CACHE_NEW) != 0) &&
2055*7c478bd9Sstevel@tonic-gate 		(strcmp(req, NS_CACHE_NORESP)  != 0) &&
2056*7c478bd9Sstevel@tonic-gate 		(strcmp(req, NS_CACHE_NEXT)    != 0) &&
2057*7c478bd9Sstevel@tonic-gate 		(strcmp(req, NS_CACHE_WRITE)   != 0)) {
2058*7c478bd9Sstevel@tonic-gate 		return;
2059*7c478bd9Sstevel@tonic-gate 	}
2060*7c478bd9Sstevel@tonic-gate 
2061*7c478bd9Sstevel@tonic-gate 	(void) getldap_serverInfo_op(INFO_OP_GETSERVER,
2062*7c478bd9Sstevel@tonic-gate 			in->ldap_u.domainname, &outstr);
2063*7c478bd9Sstevel@tonic-gate 
2064*7c478bd9Sstevel@tonic-gate 	if (outstr == NULL)
2065*7c478bd9Sstevel@tonic-gate 		return;
2066*7c478bd9Sstevel@tonic-gate 
2067*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (ldap_return_t);
2068*7c478bd9Sstevel@tonic-gate 	(void) strncpy(out->ldap_u.config, outstr, strlen(outstr)+1);
2069*7c478bd9Sstevel@tonic-gate 
2070*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_PROFILE_REFRESH) {
2071*7c478bd9Sstevel@tonic-gate 		/* Log server IP */
2072*7c478bd9Sstevel@tonic-gate 		char *ptr;
2073*7c478bd9Sstevel@tonic-gate 		ptr = strstr(outstr, DOORLINESEP);
2074*7c478bd9Sstevel@tonic-gate 		if (ptr) {
2075*7c478bd9Sstevel@tonic-gate 			*ptr = '\0';
2076*7c478bd9Sstevel@tonic-gate 			logit("getldap_getserver: got server %s\n", outstr);
2077*7c478bd9Sstevel@tonic-gate 		} else
2078*7c478bd9Sstevel@tonic-gate 			logit("getldap_getserver: Missing %s."
2079*7c478bd9Sstevel@tonic-gate 				" Internal error\n", DOORLINESEP);
2080*7c478bd9Sstevel@tonic-gate 	}
2081*7c478bd9Sstevel@tonic-gate 	free(outstr);
2082*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = SUCCESS;
2083*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = 0;
2084*7c478bd9Sstevel@tonic-gate 
2085*7c478bd9Sstevel@tonic-gate }
2086*7c478bd9Sstevel@tonic-gate 
2087*7c478bd9Sstevel@tonic-gate void
2088*7c478bd9Sstevel@tonic-gate getldap_get_cacheData(ldap_return_t *out, ldap_call_t *in)
2089*7c478bd9Sstevel@tonic-gate {
2090*7c478bd9Sstevel@tonic-gate 	char	*outstr = NULL, *instr = NULL;
2091*7c478bd9Sstevel@tonic-gate 	int	datatype = CACHE_MAP_UNKNOWN;
2092*7c478bd9Sstevel@tonic-gate 
2093*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2094*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_cacheData()...\n");
2095*7c478bd9Sstevel@tonic-gate 	}
2096*7c478bd9Sstevel@tonic-gate 
2097*7c478bd9Sstevel@tonic-gate 	/* assume no cache data found */
2098*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = -1;
2099*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = NOTFOUND;
2100*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (*out);
2101*7c478bd9Sstevel@tonic-gate 
2102*7c478bd9Sstevel@tonic-gate 	/* make sure the request is valid */
2103*7c478bd9Sstevel@tonic-gate 	if (strncmp(in->ldap_u.servername,
2104*7c478bd9Sstevel@tonic-gate 		NS_CACHE_DN2DOMAIN, strlen(NS_CACHE_DN2DOMAIN)) == 0)
2105*7c478bd9Sstevel@tonic-gate 		datatype = CACHE_MAP_DN2DOMAIN;
2106*7c478bd9Sstevel@tonic-gate 
2107*7c478bd9Sstevel@tonic-gate 	if (datatype == CACHE_MAP_UNKNOWN)
2108*7c478bd9Sstevel@tonic-gate 		return;
2109*7c478bd9Sstevel@tonic-gate 
2110*7c478bd9Sstevel@tonic-gate 	instr = strstr(in->ldap_u.servername, DOORLINESEP);
2111*7c478bd9Sstevel@tonic-gate 	if (instr == NULL)
2112*7c478bd9Sstevel@tonic-gate 		return;
2113*7c478bd9Sstevel@tonic-gate 	instr += strlen(DOORLINESEP);
2114*7c478bd9Sstevel@tonic-gate 	if (*instr == '\0')
2115*7c478bd9Sstevel@tonic-gate 		return;
2116*7c478bd9Sstevel@tonic-gate 
2117*7c478bd9Sstevel@tonic-gate 	(void) getldap_cache_op(CACHE_OP_FIND, datatype,
2118*7c478bd9Sstevel@tonic-gate 			instr, &outstr);
2119*7c478bd9Sstevel@tonic-gate 
2120*7c478bd9Sstevel@tonic-gate 	if (outstr == NULL)
2121*7c478bd9Sstevel@tonic-gate 		return;
2122*7c478bd9Sstevel@tonic-gate 
2123*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (ldap_return_t);
2124*7c478bd9Sstevel@tonic-gate 	(void) strncpy(out->ldap_u.config, outstr, strlen(outstr)+1);
2125*7c478bd9Sstevel@tonic-gate 	free(outstr);
2126*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = SUCCESS;
2127*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = 0;
2128*7c478bd9Sstevel@tonic-gate }
2129*7c478bd9Sstevel@tonic-gate 
2130*7c478bd9Sstevel@tonic-gate void
2131*7c478bd9Sstevel@tonic-gate getldap_set_cacheData(ldap_return_t *out, ldap_call_t *in)
2132*7c478bd9Sstevel@tonic-gate {
2133*7c478bd9Sstevel@tonic-gate 	char	*instr1 = NULL;
2134*7c478bd9Sstevel@tonic-gate 	char	*instr2 = NULL;
2135*7c478bd9Sstevel@tonic-gate 	int	datatype = CACHE_MAP_UNKNOWN;
2136*7c478bd9Sstevel@tonic-gate 	int	rc = 0;
2137*7c478bd9Sstevel@tonic-gate 
2138*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2139*7c478bd9Sstevel@tonic-gate 		logit("getldap_set_cacheData()...\n");
2140*7c478bd9Sstevel@tonic-gate 	}
2141*7c478bd9Sstevel@tonic-gate 
2142*7c478bd9Sstevel@tonic-gate 	/* assume error */
2143*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = -1;
2144*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = NOTFOUND;
2145*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (*out);
2146*7c478bd9Sstevel@tonic-gate 
2147*7c478bd9Sstevel@tonic-gate 	/* make sure the request is valid */
2148*7c478bd9Sstevel@tonic-gate 	if (strncmp(in->ldap_u.servername,
2149*7c478bd9Sstevel@tonic-gate 		NS_CACHE_DN2DOMAIN, strlen(NS_CACHE_DN2DOMAIN)) == 0)
2150*7c478bd9Sstevel@tonic-gate 		datatype = CACHE_MAP_DN2DOMAIN;
2151*7c478bd9Sstevel@tonic-gate 
2152*7c478bd9Sstevel@tonic-gate 	if (datatype == CACHE_MAP_UNKNOWN)
2153*7c478bd9Sstevel@tonic-gate 		return;
2154*7c478bd9Sstevel@tonic-gate 
2155*7c478bd9Sstevel@tonic-gate 	instr1 = strstr(in->ldap_u.servername, DOORLINESEP);
2156*7c478bd9Sstevel@tonic-gate 	if (instr1 == NULL)
2157*7c478bd9Sstevel@tonic-gate 		return;
2158*7c478bd9Sstevel@tonic-gate 	*instr1 = '\0';
2159*7c478bd9Sstevel@tonic-gate 	instr1 += strlen(DOORLINESEP);
2160*7c478bd9Sstevel@tonic-gate 	if (*instr1 == '\0')
2161*7c478bd9Sstevel@tonic-gate 		return;
2162*7c478bd9Sstevel@tonic-gate 	instr2 = strstr(instr1, DOORLINESEP);
2163*7c478bd9Sstevel@tonic-gate 	if (instr2 == NULL)
2164*7c478bd9Sstevel@tonic-gate 		return;
2165*7c478bd9Sstevel@tonic-gate 	*instr2 = '\0';
2166*7c478bd9Sstevel@tonic-gate 	instr2 += strlen(DOORLINESEP);
2167*7c478bd9Sstevel@tonic-gate 	if (*instr2 == '\0')
2168*7c478bd9Sstevel@tonic-gate 		return;
2169*7c478bd9Sstevel@tonic-gate 
2170*7c478bd9Sstevel@tonic-gate 	rc = getldap_cache_op(CACHE_OP_ADD, datatype,
2171*7c478bd9Sstevel@tonic-gate 			instr1, &instr2);
2172*7c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
2173*7c478bd9Sstevel@tonic-gate 		return;
2174*7c478bd9Sstevel@tonic-gate 
2175*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (ldap_return_t);
2176*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = SUCCESS;
2177*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = 0;
2178*7c478bd9Sstevel@tonic-gate }
2179*7c478bd9Sstevel@tonic-gate 
2180*7c478bd9Sstevel@tonic-gate void
2181*7c478bd9Sstevel@tonic-gate getldap_get_cacheStat(ldap_return_t *out)
2182*7c478bd9Sstevel@tonic-gate {
2183*7c478bd9Sstevel@tonic-gate 	char	*foutstr = NULL;
2184*7c478bd9Sstevel@tonic-gate 	char	*soutstr = NULL;
2185*7c478bd9Sstevel@tonic-gate 	char	*coutstr = NULL;
2186*7c478bd9Sstevel@tonic-gate 
2187*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2188*7c478bd9Sstevel@tonic-gate 		logit("getldap_get_cacheStat()...\n");
2189*7c478bd9Sstevel@tonic-gate 	}
2190*7c478bd9Sstevel@tonic-gate 
2191*7c478bd9Sstevel@tonic-gate 	/* setup for error return */
2192*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = -1;
2193*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = NOTFOUND;
2194*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (*out);
2195*7c478bd9Sstevel@tonic-gate 
2196*7c478bd9Sstevel@tonic-gate 	/* get refersh statisitcs */
2197*7c478bd9Sstevel@tonic-gate 	(void) getldap_get_refresh_stat(&foutstr);
2198*7c478bd9Sstevel@tonic-gate 	if (foutstr == NULL)
2199*7c478bd9Sstevel@tonic-gate 		return;
2200*7c478bd9Sstevel@tonic-gate 
2201*7c478bd9Sstevel@tonic-gate 	/* get server statisitcs */
2202*7c478bd9Sstevel@tonic-gate 	(void) getldap_serverInfo_op(INFO_OP_GETSTAT, NULL, &soutstr);
2203*7c478bd9Sstevel@tonic-gate 	if (soutstr == NULL) {
2204*7c478bd9Sstevel@tonic-gate 		free(foutstr);
2205*7c478bd9Sstevel@tonic-gate 		return;
2206*7c478bd9Sstevel@tonic-gate 	}
2207*7c478bd9Sstevel@tonic-gate 	/* get cache data statisitcs */
2208*7c478bd9Sstevel@tonic-gate 	(void) getldap_cache_op(CACHE_OP_GETSTAT, NULL, NULL, &coutstr);
2209*7c478bd9Sstevel@tonic-gate 	if (coutstr == NULL) {
2210*7c478bd9Sstevel@tonic-gate 		free(foutstr);
2211*7c478bd9Sstevel@tonic-gate 		free(soutstr);
2212*7c478bd9Sstevel@tonic-gate 		return;
2213*7c478bd9Sstevel@tonic-gate 	}
2214*7c478bd9Sstevel@tonic-gate 
2215*7c478bd9Sstevel@tonic-gate 	out->ldap_bufferbytesused = sizeof (ldap_return_t);
2216*7c478bd9Sstevel@tonic-gate 	(void) strncpy(out->ldap_u.config, foutstr, strlen(foutstr) + 1);
2217*7c478bd9Sstevel@tonic-gate 	(void) strncat(out->ldap_u.config, soutstr, strlen(soutstr) + 1);
2218*7c478bd9Sstevel@tonic-gate 	(void) strncat(out->ldap_u.config, coutstr, strlen(coutstr) + 1);
2219*7c478bd9Sstevel@tonic-gate 
2220*7c478bd9Sstevel@tonic-gate 	free(foutstr);
2221*7c478bd9Sstevel@tonic-gate 	free(soutstr);
2222*7c478bd9Sstevel@tonic-gate 	free(coutstr);
2223*7c478bd9Sstevel@tonic-gate 
2224*7c478bd9Sstevel@tonic-gate 	out->ldap_return_code = SUCCESS;
2225*7c478bd9Sstevel@tonic-gate 	out->ldap_errno = 0;
2226*7c478bd9Sstevel@tonic-gate }
2227*7c478bd9Sstevel@tonic-gate 
2228*7c478bd9Sstevel@tonic-gate static int
2229*7c478bd9Sstevel@tonic-gate checkupdate(int sighup)
2230*7c478bd9Sstevel@tonic-gate {
2231*7c478bd9Sstevel@tonic-gate 	int	value;
2232*7c478bd9Sstevel@tonic-gate 
2233*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&ldap_lock);
2234*7c478bd9Sstevel@tonic-gate 	value = sighup;
2235*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2236*7c478bd9Sstevel@tonic-gate 
2237*7c478bd9Sstevel@tonic-gate 	return (value == TRUE);
2238*7c478bd9Sstevel@tonic-gate }
2239*7c478bd9Sstevel@tonic-gate 
2240*7c478bd9Sstevel@tonic-gate 
2241*7c478bd9Sstevel@tonic-gate static int
2242*7c478bd9Sstevel@tonic-gate update_from_profile()
2243*7c478bd9Sstevel@tonic-gate {
2244*7c478bd9Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
2245*7c478bd9Sstevel@tonic-gate 	char		searchfilter[BUFSIZ];
2246*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error;
2247*7c478bd9Sstevel@tonic-gate 	int		rc;
2248*7c478bd9Sstevel@tonic-gate 	void		**paramVal = NULL;
2249*7c478bd9Sstevel@tonic-gate 	ns_config_t	*ptr = NULL;
2250*7c478bd9Sstevel@tonic-gate 	char		*profile = NULL;
2251*7c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
2252*7c478bd9Sstevel@tonic-gate 
2253*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2254*7c478bd9Sstevel@tonic-gate 		logit("update_from_profile....\n");
2255*7c478bd9Sstevel@tonic-gate 	}
2256*7c478bd9Sstevel@tonic-gate 	do {
2257*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&ldap_lock);
2258*7c478bd9Sstevel@tonic-gate 		sighup_update = FALSE;
2259*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ldap_lock);
2260*7c478bd9Sstevel@tonic-gate 
2261*7c478bd9Sstevel@tonic-gate 		if ((rc = __ns_ldap_getParam(NS_LDAP_PROFILE_P,
2262*7c478bd9Sstevel@tonic-gate 			&paramVal, &error)) != NS_LDAP_SUCCESS) {
2263*7c478bd9Sstevel@tonic-gate 			if (error != NULL && error->message != NULL)
2264*7c478bd9Sstevel@tonic-gate 				logit("Error: Unable to  profile name: %s\n",
2265*7c478bd9Sstevel@tonic-gate 					error->message);
2266*7c478bd9Sstevel@tonic-gate 			else {
2267*7c478bd9Sstevel@tonic-gate 				char *tmp;
2268*7c478bd9Sstevel@tonic-gate 
2269*7c478bd9Sstevel@tonic-gate 				__ns_ldap_err2str(rc, &tmp);
2270*7c478bd9Sstevel@tonic-gate 				logit("Error: Unable to  profile name: %s\n",
2271*7c478bd9Sstevel@tonic-gate 					tmp);
2272*7c478bd9Sstevel@tonic-gate 			}
2273*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
2274*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
2275*7c478bd9Sstevel@tonic-gate 			return (-1);
2276*7c478bd9Sstevel@tonic-gate 		}
2277*7c478bd9Sstevel@tonic-gate 
2278*7c478bd9Sstevel@tonic-gate 		if (paramVal && *paramVal)
2279*7c478bd9Sstevel@tonic-gate 			profile = strdup((char *)*paramVal);
2280*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
2281*7c478bd9Sstevel@tonic-gate 
2282*7c478bd9Sstevel@tonic-gate 		if (profile == NULL) {
2283*7c478bd9Sstevel@tonic-gate 			return (-1);
2284*7c478bd9Sstevel@tonic-gate 		}
2285*7c478bd9Sstevel@tonic-gate 
2286*7c478bd9Sstevel@tonic-gate 		(void) snprintf(searchfilter, BUFSIZ, _PROFILE_FILTER,
2287*7c478bd9Sstevel@tonic-gate 		    _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile);
2288*7c478bd9Sstevel@tonic-gate 
2289*7c478bd9Sstevel@tonic-gate 		if ((rc = __ns_ldap_list(_PROFILE_CONTAINER,
2290*7c478bd9Sstevel@tonic-gate 		    (const char *)searchfilter, NULL,
2291*7c478bd9Sstevel@tonic-gate 		    NULL, NULL, 0,
2292*7c478bd9Sstevel@tonic-gate 		    &result, &error, NULL, NULL)) != NS_LDAP_SUCCESS) {
2293*7c478bd9Sstevel@tonic-gate 
2294*7c478bd9Sstevel@tonic-gate 			/*
2295*7c478bd9Sstevel@tonic-gate 			 * Is profile name the DEFAULTCONFIGNAME?
2296*7c478bd9Sstevel@tonic-gate 			 * syslog Warning, otherwise syslog error.
2297*7c478bd9Sstevel@tonic-gate 			 */
2298*7c478bd9Sstevel@tonic-gate 			if (strcmp(profile, DEFAULTCONFIGNAME) == 0) {
2299*7c478bd9Sstevel@tonic-gate 				syslog(LOG_WARNING,
2300*7c478bd9Sstevel@tonic-gate 				    "Ignoring attempt to refresh nonexistent "
2301*7c478bd9Sstevel@tonic-gate 				    "default profile: %s.\n",
2302*7c478bd9Sstevel@tonic-gate 				    profile);
2303*7c478bd9Sstevel@tonic-gate 				logit("Ignoring attempt to refresh nonexistent "
2304*7c478bd9Sstevel@tonic-gate 				    "default profile: %s.\n",
2305*7c478bd9Sstevel@tonic-gate 				    profile);
2306*7c478bd9Sstevel@tonic-gate 			} else if ((error != NULL) &&
2307*7c478bd9Sstevel@tonic-gate 			    (error->message != NULL)) {
2308*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
2309*7c478bd9Sstevel@tonic-gate 				    "Error: Unable to refresh profile:%s:"
2310*7c478bd9Sstevel@tonic-gate 				    " %s\n", profile, error->message);
2311*7c478bd9Sstevel@tonic-gate 				logit("Error: Unable to refresh profile:"
2312*7c478bd9Sstevel@tonic-gate 					"%s:%s\n", profile, error->message);
2313*7c478bd9Sstevel@tonic-gate 			} else {
2314*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "Error: Unable to refresh "
2315*7c478bd9Sstevel@tonic-gate 					"from profile:%s. (error=%d)\n",
2316*7c478bd9Sstevel@tonic-gate 					profile, rc);
2317*7c478bd9Sstevel@tonic-gate 				logit("Error: Unable to refresh from profile "
2318*7c478bd9Sstevel@tonic-gate 					"%s (error=%d)\n", profile, rc);
2319*7c478bd9Sstevel@tonic-gate 			}
2320*7c478bd9Sstevel@tonic-gate 
2321*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
2322*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeResult(&result);
2323*7c478bd9Sstevel@tonic-gate 			free(profile);
2324*7c478bd9Sstevel@tonic-gate 			return (-1);
2325*7c478bd9Sstevel@tonic-gate 		}
2326*7c478bd9Sstevel@tonic-gate 		free(profile);
2327*7c478bd9Sstevel@tonic-gate 
2328*7c478bd9Sstevel@tonic-gate 
2329*7c478bd9Sstevel@tonic-gate 	} while (checkupdate(sighup_update) == TRUE);
2330*7c478bd9Sstevel@tonic-gate 
2331*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&ldap_lock);
2332*7c478bd9Sstevel@tonic-gate 
2333*7c478bd9Sstevel@tonic-gate 	ptr = __ns_ldap_make_config(result);
2334*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
2335*7c478bd9Sstevel@tonic-gate 
2336*7c478bd9Sstevel@tonic-gate 	if (ptr == NULL) {
2337*7c478bd9Sstevel@tonic-gate 		logit("Error: __ns_ldap_make_config failed.\n");
2338*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ldap_lock);
2339*7c478bd9Sstevel@tonic-gate 		return (-1);
2340*7c478bd9Sstevel@tonic-gate 	}
2341*7c478bd9Sstevel@tonic-gate 
2342*7c478bd9Sstevel@tonic-gate 	/*
2343*7c478bd9Sstevel@tonic-gate 	 * cross check the config parameters
2344*7c478bd9Sstevel@tonic-gate 	 */
2345*7c478bd9Sstevel@tonic-gate 	if (__s_api_crosscheck(ptr, errstr, B_TRUE) == NS_SUCCESS) {
2346*7c478bd9Sstevel@tonic-gate 		/*
2347*7c478bd9Sstevel@tonic-gate 		 * reset the local profile TTL
2348*7c478bd9Sstevel@tonic-gate 		 */
2349*7c478bd9Sstevel@tonic-gate 		if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc)
2350*7c478bd9Sstevel@tonic-gate 			current_admin.ldap_stat.ldap_ttl =
2351*7c478bd9Sstevel@tonic-gate 			atol(ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc);
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate 		if (current_admin.debug_level >= DBG_PROFILE_REFRESH) {
2354*7c478bd9Sstevel@tonic-gate 			logit("update_from_profile: reset profile TTL to %d"
2355*7c478bd9Sstevel@tonic-gate 				"  seconds\n",
2356*7c478bd9Sstevel@tonic-gate 				current_admin.ldap_stat.ldap_ttl);
2357*7c478bd9Sstevel@tonic-gate 			logit("update_from_profile: expire time %d "
2358*7c478bd9Sstevel@tonic-gate 				"seconds\n",
2359*7c478bd9Sstevel@tonic-gate 				*ptr->paramList[NS_LDAP_EXP_P].ns_pi);
2360*7c478bd9Sstevel@tonic-gate 		}
2361*7c478bd9Sstevel@tonic-gate 
2362*7c478bd9Sstevel@tonic-gate 		/* set ptr as current_config */
2363*7c478bd9Sstevel@tonic-gate 		__s_api_init_config(ptr);
2364*7c478bd9Sstevel@tonic-gate 		rc = 0;
2365*7c478bd9Sstevel@tonic-gate 	} else {
2366*7c478bd9Sstevel@tonic-gate 		__s_api_destroy_config(ptr);
2367*7c478bd9Sstevel@tonic-gate 		logit("Error: downloaded profile failed to pass "
2368*7c478bd9Sstevel@tonic-gate 			"crosscheck (%s).\n", errstr);
2369*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "ldap_cachemgr: %s", errstr);
2370*7c478bd9Sstevel@tonic-gate 		rc = -1;
2371*7c478bd9Sstevel@tonic-gate 	}
2372*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2373*7c478bd9Sstevel@tonic-gate 	return (rc);
2374*7c478bd9Sstevel@tonic-gate }
2375*7c478bd9Sstevel@tonic-gate 
2376*7c478bd9Sstevel@tonic-gate int
2377*7c478bd9Sstevel@tonic-gate getldap_init()
2378*7c478bd9Sstevel@tonic-gate {
2379*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error;
2380*7c478bd9Sstevel@tonic-gate 	struct timeval	tp;
2381*7c478bd9Sstevel@tonic-gate 
2382*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2383*7c478bd9Sstevel@tonic-gate 		logit("getldap_init()...\n");
2384*7c478bd9Sstevel@tonic-gate 	}
2385*7c478bd9Sstevel@tonic-gate 
2386*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_setServer(TRUE);
2387*7c478bd9Sstevel@tonic-gate 
2388*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&ldap_lock);
2389*7c478bd9Sstevel@tonic-gate 	if ((error = __ns_ldap_LoadConfiguration()) != NULL) {
2390*7c478bd9Sstevel@tonic-gate 		logit("Error: Unable to read '%s': %s\n",
2391*7c478bd9Sstevel@tonic-gate 			NSCONFIGFILE, error->message);
2392*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
2393*7c478bd9Sstevel@tonic-gate 			gettext("\nError: Unable to read '%s': %s\n"),
2394*7c478bd9Sstevel@tonic-gate 			NSCONFIGFILE, error->message);
2395*7c478bd9Sstevel@tonic-gate 		__ns_ldap_freeError(&error);
2396*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ldap_lock);
2397*7c478bd9Sstevel@tonic-gate 		return (-1);
2398*7c478bd9Sstevel@tonic-gate 	}
2399*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2400*7c478bd9Sstevel@tonic-gate 
2401*7c478bd9Sstevel@tonic-gate 	if (gettimeofday(&tp, NULL) == 0) {
2402*7c478bd9Sstevel@tonic-gate 		/* statistics: previous refresh time */
2403*7c478bd9Sstevel@tonic-gate 		prev_refresh_time = tp.tv_sec;
2404*7c478bd9Sstevel@tonic-gate 	}
2405*7c478bd9Sstevel@tonic-gate 
2406*7c478bd9Sstevel@tonic-gate 	/* initialize the data cache */
2407*7c478bd9Sstevel@tonic-gate 	(void) getldap_cache_op(CACHE_OP_CREATE,
2408*7c478bd9Sstevel@tonic-gate 			0, NULL, NULL);
2409*7c478bd9Sstevel@tonic-gate 
2410*7c478bd9Sstevel@tonic-gate 	return (0);
2411*7c478bd9Sstevel@tonic-gate }
2412*7c478bd9Sstevel@tonic-gate 
2413*7c478bd9Sstevel@tonic-gate static void
2414*7c478bd9Sstevel@tonic-gate perform_update(void)
2415*7c478bd9Sstevel@tonic-gate {
2416*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error;
2417*7c478bd9Sstevel@tonic-gate 	struct timeval	tp;
2418*7c478bd9Sstevel@tonic-gate 	char		buf[20];
2419*7c478bd9Sstevel@tonic-gate 	int		rc;
2420*7c478bd9Sstevel@tonic-gate 
2421*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2422*7c478bd9Sstevel@tonic-gate 		logit("perform_update()...\n");
2423*7c478bd9Sstevel@tonic-gate 	}
2424*7c478bd9Sstevel@tonic-gate 
2425*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_setServer(TRUE);
2426*7c478bd9Sstevel@tonic-gate 
2427*7c478bd9Sstevel@tonic-gate 	if (gettimeofday(&tp, NULL) != 0)
2428*7c478bd9Sstevel@tonic-gate 		return;
2429*7c478bd9Sstevel@tonic-gate 
2430*7c478bd9Sstevel@tonic-gate 	/*
2431*7c478bd9Sstevel@tonic-gate 	 * set the profile TTL parameter, just
2432*7c478bd9Sstevel@tonic-gate 	 * in case that the downloading of
2433*7c478bd9Sstevel@tonic-gate 	 * the profile from server would fail
2434*7c478bd9Sstevel@tonic-gate 	 */
2435*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_PROFILE_REFRESH) {
2436*7c478bd9Sstevel@tonic-gate 		logit("perform_update: current profile TTL is %d seconds\n",
2437*7c478bd9Sstevel@tonic-gate 			current_admin.ldap_stat.ldap_ttl);
2438*7c478bd9Sstevel@tonic-gate 	}
2439*7c478bd9Sstevel@tonic-gate 	/*
2440*7c478bd9Sstevel@tonic-gate 	 * NS_LDAP_EXP_P is a no op for __ns_ldap_setParam
2441*7c478bd9Sstevel@tonic-gate 	 * It depends on NS_LDAP_CACHETTL_P to set it's value
2442*7c478bd9Sstevel@tonic-gate 	 * Set NS_LDAP_CACHETTL_P here so NS_LDAP_EXP_P value
2443*7c478bd9Sstevel@tonic-gate 	 * can be set.
2444*7c478bd9Sstevel@tonic-gate 	 * NS_LDAP_CACHETTL_P value can be reset after the profile is
2445*7c478bd9Sstevel@tonic-gate 	 * downloaded from the server, so is NS_LDAP_EXP_P.
2446*7c478bd9Sstevel@tonic-gate 	 */
2447*7c478bd9Sstevel@tonic-gate 	buf[19] = '\0'; /* null terminated the buffer */
2448*7c478bd9Sstevel@tonic-gate 	if (__ns_ldap_setParam(NS_LDAP_CACHETTL_P,
2449*7c478bd9Sstevel@tonic-gate 		lltostr((long long)current_admin.ldap_stat.ldap_ttl, &buf[19]),
2450*7c478bd9Sstevel@tonic-gate 		&error) != NS_LDAP_SUCCESS) {
2451*7c478bd9Sstevel@tonic-gate 		logit("Error: __ns_ldap_setParam failed, status: %d "
2452*7c478bd9Sstevel@tonic-gate 			"message: %s\n", error->status, error->message);
2453*7c478bd9Sstevel@tonic-gate 		__ns_ldap_freeError(&error);
2454*7c478bd9Sstevel@tonic-gate 		return;
2455*7c478bd9Sstevel@tonic-gate 	}
2456*7c478bd9Sstevel@tonic-gate 
2457*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&ldap_lock);
2458*7c478bd9Sstevel@tonic-gate 	sighup_update = FALSE;
2459*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2460*7c478bd9Sstevel@tonic-gate 
2461*7c478bd9Sstevel@tonic-gate 	do {
2462*7c478bd9Sstevel@tonic-gate 		rc = update_from_profile();
2463*7c478bd9Sstevel@tonic-gate 		if (rc != 0) {
2464*7c478bd9Sstevel@tonic-gate 			logit("Error: Unable to update from profile\n");
2465*7c478bd9Sstevel@tonic-gate 		}
2466*7c478bd9Sstevel@tonic-gate 	} while (checkupdate(sighup_update) == TRUE);
2467*7c478bd9Sstevel@tonic-gate 
2468*7c478bd9Sstevel@tonic-gate 	/*
2469*7c478bd9Sstevel@tonic-gate 	 * recreate the server info list
2470*7c478bd9Sstevel@tonic-gate 	 */
2471*7c478bd9Sstevel@tonic-gate 	if (rc == 0) {
2472*7c478bd9Sstevel@tonic-gate 		(void) getldap_serverInfo_op(INFO_OP_CREATE, NULL, NULL);
2473*7c478bd9Sstevel@tonic-gate 
2474*7c478bd9Sstevel@tonic-gate 		/* flush the data cache */
2475*7c478bd9Sstevel@tonic-gate 		(void) getldap_cache_op(CACHE_OP_DELETE,
2476*7c478bd9Sstevel@tonic-gate 				0, NULL, NULL);
2477*7c478bd9Sstevel@tonic-gate 
2478*7c478bd9Sstevel@tonic-gate 		/* statistics: previous refresh time */
2479*7c478bd9Sstevel@tonic-gate 		prev_refresh_time = tp.tv_sec;
2480*7c478bd9Sstevel@tonic-gate 	}
2481*7c478bd9Sstevel@tonic-gate 
2482*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&ldap_lock);
2483*7c478bd9Sstevel@tonic-gate 	if ((error = __ns_ldap_DumpConfiguration(NSCONFIGREFRESH)) != NULL) {
2484*7c478bd9Sstevel@tonic-gate 		logit("Error: __ns_ldap_DumpConfiguration(\"%s\") failed, "
2485*7c478bd9Sstevel@tonic-gate 		    "status: %d "
2486*7c478bd9Sstevel@tonic-gate 		    "message: %s\n", NSCONFIGREFRESH,
2487*7c478bd9Sstevel@tonic-gate 		    error->status, error->message);
2488*7c478bd9Sstevel@tonic-gate 		__ns_ldap_freeError(&error);
2489*7c478bd9Sstevel@tonic-gate 	}
2490*7c478bd9Sstevel@tonic-gate 	if ((error = __ns_ldap_DumpConfiguration(NSCREDREFRESH)) != NULL) {
2491*7c478bd9Sstevel@tonic-gate 		logit("Error: __ns_ldap_DumpConfiguration(\"%s\") failed, "
2492*7c478bd9Sstevel@tonic-gate 		    "status: %d "
2493*7c478bd9Sstevel@tonic-gate 		    "message: %s\n", NSCREDREFRESH,
2494*7c478bd9Sstevel@tonic-gate 		    error->status, error->message);
2495*7c478bd9Sstevel@tonic-gate 		__ns_ldap_freeError(&error);
2496*7c478bd9Sstevel@tonic-gate 	}
2497*7c478bd9Sstevel@tonic-gate 	if (rename(NSCONFIGREFRESH, NSCONFIGFILE) != 0)
2498*7c478bd9Sstevel@tonic-gate 		logit("Error: unlink failed - errno: %d\n", errno);
2499*7c478bd9Sstevel@tonic-gate 	if (rename(NSCREDREFRESH, NSCREDFILE) != 0)
2500*7c478bd9Sstevel@tonic-gate 		logit("Error: unlink failed - errno: %d\n", errno);
2501*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2502*7c478bd9Sstevel@tonic-gate 
2503*7c478bd9Sstevel@tonic-gate }
2504*7c478bd9Sstevel@tonic-gate 
2505*7c478bd9Sstevel@tonic-gate void
2506*7c478bd9Sstevel@tonic-gate getldap_refresh()
2507*7c478bd9Sstevel@tonic-gate {
2508*7c478bd9Sstevel@tonic-gate 	struct timespec	timeout;
2509*7c478bd9Sstevel@tonic-gate 	int		sleeptime;
2510*7c478bd9Sstevel@tonic-gate 	struct timeval	tp;
2511*7c478bd9Sstevel@tonic-gate 	long		expire = 0;
2512*7c478bd9Sstevel@tonic-gate 	void		**paramVal = NULL;
2513*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
2514*7c478bd9Sstevel@tonic-gate 	int		always = 1, err;
2515*7c478bd9Sstevel@tonic-gate 	int		first_time = 1;
2516*7c478bd9Sstevel@tonic-gate 	int		sig_done = 0;
2517*7c478bd9Sstevel@tonic-gate 	int		dbg_level;
2518*7c478bd9Sstevel@tonic-gate 
2519*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2520*7c478bd9Sstevel@tonic-gate 		logit("getldap_refresh()...\n");
2521*7c478bd9Sstevel@tonic-gate 	}
2522*7c478bd9Sstevel@tonic-gate 
2523*7c478bd9Sstevel@tonic-gate 	/*
2524*7c478bd9Sstevel@tonic-gate 	 * wait for an available server
2525*7c478bd9Sstevel@tonic-gate 	 */
2526*7c478bd9Sstevel@tonic-gate 	while (sig_done == 0) {
2527*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&sig_mutex);
2528*7c478bd9Sstevel@tonic-gate 		sig_done = signal_done;
2529*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&sig_mutex);
2530*7c478bd9Sstevel@tonic-gate 	}
2531*7c478bd9Sstevel@tonic-gate 
2532*7c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_setServer(TRUE);
2533*7c478bd9Sstevel@tonic-gate 	while (always) {
2534*7c478bd9Sstevel@tonic-gate 		dbg_level = current_admin.debug_level;
2535*7c478bd9Sstevel@tonic-gate 		(void) rw_rdlock(&ldap_lock);
2536*7c478bd9Sstevel@tonic-gate 		sleeptime = current_admin.ldap_stat.ldap_ttl;
2537*7c478bd9Sstevel@tonic-gate 		if (dbg_level >= DBG_PROFILE_REFRESH) {
2538*7c478bd9Sstevel@tonic-gate 			logit("getldap_refresh: current profile TTL is %d "
2539*7c478bd9Sstevel@tonic-gate 			"seconds\n", current_admin.ldap_stat.ldap_ttl);
2540*7c478bd9Sstevel@tonic-gate 		}
2541*7c478bd9Sstevel@tonic-gate 		if (gettimeofday(&tp, NULL) == 0) {
2542*7c478bd9Sstevel@tonic-gate 			if ((__ns_ldap_getParam(NS_LDAP_EXP_P,
2543*7c478bd9Sstevel@tonic-gate 			    &paramVal, &errorp) == NS_LDAP_SUCCESS) &&
2544*7c478bd9Sstevel@tonic-gate 			    paramVal != NULL &&
2545*7c478bd9Sstevel@tonic-gate 			    (char *)*paramVal != NULL) {
2546*7c478bd9Sstevel@tonic-gate 				errno = 0;
2547*7c478bd9Sstevel@tonic-gate 				expire = atol((char *)*paramVal);
2548*7c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeParam(&paramVal);
2549*7c478bd9Sstevel@tonic-gate 				if (errno == 0) {
2550*7c478bd9Sstevel@tonic-gate 					if (expire == 0) {
2551*7c478bd9Sstevel@tonic-gate 						first_time = 0;
2552*7c478bd9Sstevel@tonic-gate 						(void) rw_unlock(&ldap_lock);
2553*7c478bd9Sstevel@tonic-gate 						(void) cond_init(&cond,
2554*7c478bd9Sstevel@tonic-gate 							NULL, NULL);
2555*7c478bd9Sstevel@tonic-gate 						(void) mutex_lock(&sighuplock);
2556*7c478bd9Sstevel@tonic-gate 						timeout.tv_sec =
2557*7c478bd9Sstevel@tonic-gate 							CACHESLEEPTIME;
2558*7c478bd9Sstevel@tonic-gate 						timeout.tv_nsec = 0;
2559*7c478bd9Sstevel@tonic-gate 						if (dbg_level >=
2560*7c478bd9Sstevel@tonic-gate 							DBG_PROFILE_REFRESH) {
2561*7c478bd9Sstevel@tonic-gate 						    logit("getldap_refresh: "
2562*7c478bd9Sstevel@tonic-gate 						    "(1)about to sleep for %d "
2563*7c478bd9Sstevel@tonic-gate 						    "seconds\n",
2564*7c478bd9Sstevel@tonic-gate 						    CACHESLEEPTIME);
2565*7c478bd9Sstevel@tonic-gate 						}
2566*7c478bd9Sstevel@tonic-gate 						err = cond_reltimedwait(&cond,
2567*7c478bd9Sstevel@tonic-gate 							&sighuplock, &timeout);
2568*7c478bd9Sstevel@tonic-gate 						(void) cond_destroy(&cond);
2569*7c478bd9Sstevel@tonic-gate 						(void) mutex_unlock(
2570*7c478bd9Sstevel@tonic-gate 							&sighuplock);
2571*7c478bd9Sstevel@tonic-gate 						/*
2572*7c478bd9Sstevel@tonic-gate 						 * if woke up by
2573*7c478bd9Sstevel@tonic-gate 						 * getldap_revalidate(),
2574*7c478bd9Sstevel@tonic-gate 						 * do update right away
2575*7c478bd9Sstevel@tonic-gate 						 */
2576*7c478bd9Sstevel@tonic-gate 						if (err == ETIME)
2577*7c478bd9Sstevel@tonic-gate 							continue;
2578*7c478bd9Sstevel@tonic-gate 						else {
2579*7c478bd9Sstevel@tonic-gate 							/*
2580*7c478bd9Sstevel@tonic-gate 							 * if load
2581*7c478bd9Sstevel@tonic-gate 							 * configuration failed
2582*7c478bd9Sstevel@tonic-gate 							 * don't do update
2583*7c478bd9Sstevel@tonic-gate 							 */
2584*7c478bd9Sstevel@tonic-gate 							if (load_config())
2585*7c478bd9Sstevel@tonic-gate 							    perform_update();
2586*7c478bd9Sstevel@tonic-gate 							continue;
2587*7c478bd9Sstevel@tonic-gate 						}
2588*7c478bd9Sstevel@tonic-gate 					}
2589*7c478bd9Sstevel@tonic-gate 					sleeptime = expire - tp.tv_sec;
2590*7c478bd9Sstevel@tonic-gate 					if (dbg_level >= DBG_PROFILE_REFRESH) {
2591*7c478bd9Sstevel@tonic-gate 					    logit("getldap_refresh: expire time"
2592*7c478bd9Sstevel@tonic-gate 						" = %ld\n", expire);
2593*7c478bd9Sstevel@tonic-gate 					}
2594*7c478bd9Sstevel@tonic-gate 
2595*7c478bd9Sstevel@tonic-gate 				}
2596*7c478bd9Sstevel@tonic-gate 			}
2597*7c478bd9Sstevel@tonic-gate 		}
2598*7c478bd9Sstevel@tonic-gate 
2599*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ldap_lock);
2600*7c478bd9Sstevel@tonic-gate 
2601*7c478bd9Sstevel@tonic-gate 		/*
2602*7c478bd9Sstevel@tonic-gate 		 * if this is the first time downloading
2603*7c478bd9Sstevel@tonic-gate 		 * the profile or expire time already passed,
2604*7c478bd9Sstevel@tonic-gate 		 * do not wait, do update
2605*7c478bd9Sstevel@tonic-gate 		 */
2606*7c478bd9Sstevel@tonic-gate 		if (first_time == 0 && sleeptime > 0) {
2607*7c478bd9Sstevel@tonic-gate 			if (dbg_level >= DBG_PROFILE_REFRESH) {
2608*7c478bd9Sstevel@tonic-gate 				logit("getldap_refresh: (2)about to sleep "
2609*7c478bd9Sstevel@tonic-gate 				"for %d seconds\n", sleeptime);
2610*7c478bd9Sstevel@tonic-gate 			}
2611*7c478bd9Sstevel@tonic-gate 			(void) cond_init(&cond, NULL, NULL);
2612*7c478bd9Sstevel@tonic-gate 			(void) mutex_lock(&sighuplock);
2613*7c478bd9Sstevel@tonic-gate 			timeout.tv_sec = sleeptime;
2614*7c478bd9Sstevel@tonic-gate 			timeout.tv_nsec = 0;
2615*7c478bd9Sstevel@tonic-gate 			err = cond_reltimedwait(&cond,
2616*7c478bd9Sstevel@tonic-gate 				&sighuplock, &timeout);
2617*7c478bd9Sstevel@tonic-gate 			(void) cond_destroy(&cond);
2618*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&sighuplock);
2619*7c478bd9Sstevel@tonic-gate 		}
2620*7c478bd9Sstevel@tonic-gate 		/*
2621*7c478bd9Sstevel@tonic-gate 		 * if load concfiguration failed
2622*7c478bd9Sstevel@tonic-gate 		 * don't do update
2623*7c478bd9Sstevel@tonic-gate 		 */
2624*7c478bd9Sstevel@tonic-gate 		if (load_config())
2625*7c478bd9Sstevel@tonic-gate 			perform_update();
2626*7c478bd9Sstevel@tonic-gate 		first_time = 0;
2627*7c478bd9Sstevel@tonic-gate 	}
2628*7c478bd9Sstevel@tonic-gate }
2629*7c478bd9Sstevel@tonic-gate 
2630*7c478bd9Sstevel@tonic-gate void
2631*7c478bd9Sstevel@tonic-gate getldap_revalidate()
2632*7c478bd9Sstevel@tonic-gate {
2633*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2634*7c478bd9Sstevel@tonic-gate 		logit("getldap_revalidate()...\n");
2635*7c478bd9Sstevel@tonic-gate 	}
2636*7c478bd9Sstevel@tonic-gate 	/* block signal SIGHUP */
2637*7c478bd9Sstevel@tonic-gate 	(void) sighold(SIGHUP);
2638*7c478bd9Sstevel@tonic-gate 
2639*7c478bd9Sstevel@tonic-gate 	/* now awake the sleeping refresh thread */
2640*7c478bd9Sstevel@tonic-gate 	(void) cond_signal(&cond);
2641*7c478bd9Sstevel@tonic-gate 
2642*7c478bd9Sstevel@tonic-gate 	/* release signal SIGHUP */
2643*7c478bd9Sstevel@tonic-gate 	(void) sigrelse(SIGHUP);
2644*7c478bd9Sstevel@tonic-gate 
2645*7c478bd9Sstevel@tonic-gate }
2646*7c478bd9Sstevel@tonic-gate 
2647*7c478bd9Sstevel@tonic-gate void
2648*7c478bd9Sstevel@tonic-gate getldap_lookup(ldap_return_t *out, ldap_call_t *in)
2649*7c478bd9Sstevel@tonic-gate {
2650*7c478bd9Sstevel@tonic-gate 	LineBuf		configinfo;
2651*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error;
2652*7c478bd9Sstevel@tonic-gate 
2653*7c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
2654*7c478bd9Sstevel@tonic-gate 		logit("getldap_lookup()...\n");
2655*7c478bd9Sstevel@tonic-gate 	}
2656*7c478bd9Sstevel@tonic-gate 
2657*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&ldap_lock);
2658*7c478bd9Sstevel@tonic-gate 	if ((error = __ns_ldap_LoadDoorInfo(&configinfo, in->ldap_u.domainname))
2659*7c478bd9Sstevel@tonic-gate 		!= NULL) {
2660*7c478bd9Sstevel@tonic-gate 		if (error != NULL && error->message != NULL)
2661*7c478bd9Sstevel@tonic-gate 			logit("Error: ldap_lookup: %s\n", error->message);
2662*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
2663*7c478bd9Sstevel@tonic-gate 		out->ldap_errno = -1;
2664*7c478bd9Sstevel@tonic-gate 		out->ldap_return_code = NOTFOUND;
2665*7c478bd9Sstevel@tonic-gate 		out->ldap_bufferbytesused = sizeof (*out);
2666*7c478bd9Sstevel@tonic-gate 
2667*7c478bd9Sstevel@tonic-gate 	} else {
2668*7c478bd9Sstevel@tonic-gate 		out->ldap_bufferbytesused = sizeof (ldap_return_t);
2669*7c478bd9Sstevel@tonic-gate 		(void) strncpy(out->ldap_u.config,
2670*7c478bd9Sstevel@tonic-gate 			configinfo.str, configinfo.len);
2671*7c478bd9Sstevel@tonic-gate 		out->ldap_return_code = SUCCESS;
2672*7c478bd9Sstevel@tonic-gate 		out->ldap_errno = 0;
2673*7c478bd9Sstevel@tonic-gate 	}
2674*7c478bd9Sstevel@tonic-gate 
2675*7c478bd9Sstevel@tonic-gate 	if (configinfo.str != NULL) {
2676*7c478bd9Sstevel@tonic-gate 		free(configinfo.str);
2677*7c478bd9Sstevel@tonic-gate 		configinfo.str = NULL;
2678*7c478bd9Sstevel@tonic-gate 		configinfo.alloc = 0;
2679*7c478bd9Sstevel@tonic-gate 		configinfo.len = 0;
2680*7c478bd9Sstevel@tonic-gate 	}
2681*7c478bd9Sstevel@tonic-gate 
2682*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ldap_lock);
2683*7c478bd9Sstevel@tonic-gate }
2684