xref: /illumos-gate/usr/src/lib/libnisdb/nis_ldap.c (revision edd580643f2cf1434e252cd7779e83182ea84945)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 #include <poll.h>
31 #include <sys/time.h>
32 #include <stdlib.h>
33 #include "nis_ldap.h"
34 #include "nis_hashitem.h"
35 #include "ldap_map.h"
36 #include "ldap_parse.h"
37 
38 
39 /*
40  * Global structure keeping config state. Since it's created and modified
41  * while the rpc.nisd still is single-threaded, and only read in MT mode,
42  * no locking is needed.
43  */
44 __nis_config_t	ldapConfig = {
45 	ini_none,			/* nisplusLDAPinitialUpdate */
46 	pass_error,			/* nisplusLDAPthreadCreationError */
47 	{
48 		-1,			/* Try forever */
49 		15			/* 15 second timeout */
50 	},
51 	de_retry,			/* nisplusLDAPdumpError */
52 	{
53 		-1,			/* Try forever */
54 		200			/* 200 second timeout */
55 	},
56 	directory_locked,		/* nisplusLDAPresyncService */
57 	accumulate,			/* nisplusLDAPupdateBatching */
58 	{
59 		-1,			/* Not used */
60 		120			/* Accumulate for 120 seconds */
61 	},
62 	block				/* nisplusLDAPexclusiveWaitMOde */
63 };
64 
65 
66 /*
67  * Utility function that accepts a (__nisdb_retry_t *), decrements the
68  * 'attempts' counter, and sleeps for 'timeout' seconds.
69  *
70  * NOTE:	Don't pass a pointer into the 'ldapConfig' structure to
71  *		this function. Instead, initialize a private copy to the
72  *		value from 'ldapConfig'.
73  *
74  * The value of 'attempts' upon entry determines action as follows:
75  *
76  *	< 0	Don't change 'attempts', sleep as indicated, return 1
77  *
78  *	  0	Don't change 'attempts', only sleep if forceSleep is set,
79  *		return 0 if we didn't sleep, 1 if we slept.
80  *
81  *	> 0	Decrement 'attempts', sleep as indicated, return 1
82  */
83 int
84 __nis_retry_sleep(__nisdb_retry_t *retry, int forceSleep) {
85 
86 	if (retry == NULL)
87 		return (0);
88 
89 	if (retry->attempts > 0) {
90 		retry->attempts -= 1;
91 	} else if (retry->attempts == 0 && !forceSleep) {
92 		return (0);
93 	}
94 
95 	(void) poll(NULL, 0, retry->timeout*1000);
96 
97 	return (1);
98 }
99 
100 /*
101  * The root directory is special in NIS+; it's the only directory that
102  * doesn't appear as an entry in another directory. Hence, our method
103  * of keeping the directory/table entry expiration time in the
104  * directory/table doesn't work, and we instead implement the following
105  * interface.
106  */
107 static time_t	rootDirExpire = 0;
108 static int	rootDirTtl = 0;
109 
110 /*
111  * Return 1 if the root dir has expired, 0 otherwise.
112  */
113 int
114 rootDirExpired(void) {
115 	struct timeval	now;
116 
117 	(void) gettimeofday(&now, 0);
118 
119 	if (rootDirExpire >= now.tv_sec)
120 		return (1);
121 	else
122 		return (0);
123 }
124 
125 /*
126  * Update the expiration time of the root dir to be now plus the TTL.
127  * Also establishes the TTL if not set.
128  */
129 int
130 touchRootDir(void) {
131 	struct timeval	now;
132 	int		ttl;
133 
134 	(void) gettimeofday(&now, 0);
135 
136 	/* Do we need to initialize the TTL ? */
137 	if (rootDirTtl == 0) {
138 		__nis_table_mapping_t	*t;
139 
140 		t = __nis_find_item_mt(ROOTDIRFILE, &ldapMappingList, 0, 0);
141 		if (t != 0) {
142 			int	interval;
143 
144 			interval = t->initTtlHi - t->initTtlLo + 1;
145 
146 			if (interval > 1) {
147 				srand48(now.tv_sec);
148 				ttl = (lrand48() % interval);
149 			} else {
150 				ttl = t->initTtlLo;
151 			}
152 
153 			rootDirTtl = t->ttl;
154 		} else {
155 			ttl = rootDirTtl = 3600;
156 		}
157 	} else {
158 		ttl = rootDirTtl;
159 	}
160 
161 	rootDirExpire = now.tv_sec + ttl;
162 
163 	return (0);
164 }
165