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
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.
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]
23 * Copyright 2015 Gary Mills
24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * DESCRIPTION: Contains utilities relating to TTL calculation.
40 #include "../ldap_util.h"
43 * Constants used in time calculations
45 #define MILLION 1000000
50 suc_code
is_greater_timeval(struct timeval
*, struct timeval
*);
51 suc_code
add_to_timeval(struct timeval
*, int);
54 * FUNCTION: has_entry_expired()
56 * DESCRIPTION: Determines if an individual entry has expired.
58 * INPUTS: Map control structure for an open map
61 * OUTPUTS: TRUE = Entry has expired or cannot be found this will cause
62 * missing entries to be pulled out of the DIT.
63 * FALSE = Entry has not expired
67 has_entry_expired(map_ctrl
*map
, datum
*key
)
71 struct timeval old_time
;
73 char *myself
= "has_entry_expired";
75 if ((map
== NULL
) || (map
->ttl
== NULL
))
78 /* Get expiry time entry for key */
79 ttl
= dbm_fetch(map
->ttl
, *key
);
81 if (NULL
== ttl
.dptr
) {
83 * If we failed to get a map expiry key, which must always be
84 * present, then something is seriously wrong. Try to recreate
87 if ((key
->dsize
== strlen(MAP_EXPIRY_KEY
)) &&
88 (0 == strncmp(key
->dptr
, MAP_EXPIRY_KEY
, key
->dsize
))) {
89 logmsg(MSG_NOTIMECHECK
, LOG_ERR
, "Cannot find %s TTL "
90 "for map %s. Will attempt to recreate map",
91 MAP_EXPIRY_KEY
, map
->map_name
);
96 * Not a problem just no TTL entry for this entry. Maybe it has
97 * not yet been downloaded. Maybe it will be handled by a
98 * service other than NIS. Check if the entire map has expired.
99 * This prevents repeated LDAP reads when requests are made for
100 * nonexistant entries.
102 if (has_map_expired(map
)) {
103 /* Kick of a map update */
104 update_map_if_required(map
, FALSE
);
107 /* Don't update the entry */
111 if (ttl
.dsize
!= sizeof (struct timeval
)) {
113 * Need to malloc some memory before can syslog the key name
114 * but this may fail. Solution log a simple message first THEn
115 * a more detailed one if it works.
117 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
118 "Invalid TTL key in map %s. error %d",
119 map
->map_name
, dbm_error(map
->ttl
));
121 /* Log the key name */
122 key_name
= (char *)am(myself
, key
->dsize
+ 1);
123 if (NULL
== key_name
) {
124 logmsg(MSG_NOMEM
, LOG_ERR
,
125 "Could not alloc memory for keyname");
127 strncpy(key_name
, key
->dptr
, key
->dsize
);
128 key_name
[key
->dsize
] = '\0';
129 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
130 "Key name was %s", key_name
);
133 /* Update it Anyway */
137 /* Get current time */
138 gettimeofday(&now
, NULL
);
141 * Because dptr may not be int aligned need to build an int
142 * out of what it points to or will get a bus error
144 bcopy(ttl
.dptr
, &old_time
, sizeof (struct timeval
));
146 return (is_greater_timeval(&now
, &old_time
));
150 * FUNCTION: has_map_expired()
152 * DESCRIPTION: Determines if an entire map has expire
154 * INPUTS: Map control structure for an open map
156 * OUTPUTS: TRUE = Map has expired
157 * FALSE Map has not expired
161 has_map_expired(map_ctrl
*map
)
165 /* Set up datum with magic expiry key */
166 key
.dsize
= strlen(MAP_EXPIRY_KEY
);
167 key
.dptr
= MAP_EXPIRY_KEY
;
169 /* Call has_entry_expired() with magic map expiry key */
170 return (has_entry_expired(map
, &key
));
174 * FUNCTION: update_entry_ttl()
176 * DESCRIPTION: Updates the TTL for one map entry
178 * INPUTS: Map control structure for an open map
180 * Flag indication if TTL should be max, min or random
182 * OUTPUTS: SUCCESS = TTL updated
183 * FAILURE = TTL not updated
188 update_entry_ttl(map_ctrl
*map
, datum
*key
, TTL_TYPE type
)
194 /* Get current time */
195 gettimeofday(&now
, NULL
);
197 /* Get TTL from mapping file */
198 ttl
= get_ttl_value(map
, type
);
200 if (FAILURE
== add_to_timeval(&now
, ttl
))
203 /* Convert time into a datum */
204 expire
.dsize
= sizeof (struct timeval
);
205 expire
.dptr
= (char *)&now
;
207 /* Set expiry time entry for key */
209 if (0 > dbm_store(map
->ttl
, *key
, expire
, DBM_REPLACE
)) {
210 logmsg(MSG_NOTIMECHECK
, LOG_ERR
, "Could not write TTL entry "
211 "(errno=%d)", errno
);
219 * FUNCTION: update_map_ttl()
221 * DESCRIPTION: Updates the TTL for entire map. This can be called either with
222 * the map open (map_ctrl DBM pointer set up) or the map closed
223 * (map_ctrl DBM pointers not set). The latter case will occur
224 * when we have just created a new map.
226 * This function must open the TTL map but, in either case, must
227 * return with the map_ctrl in it's original state.
229 * INPUTS: Map control structure for an open map
231 * OUTPUTS: SUCCESS = TTL updated
232 * FAILURE = TTL not updated
236 update_map_ttl(map_ctrl
*map
)
239 bool_t map_was_open
= TRUE
;
242 /* Set up datum with magic expiry key */
243 key
.dsize
= strlen(MAP_EXPIRY_KEY
);
244 key
.dptr
= MAP_EXPIRY_KEY
;
246 /* If TTL not open open it */
247 if (NULL
== map
->ttl
) {
248 map
->ttl
= dbm_open(map
->ttl_path
, O_RDWR
, 0644);
249 if (NULL
== map
->ttl
)
251 map_was_open
= FALSE
;
254 /* Call update_entry_ttl() with magic map expiry key */
255 ret
= update_entry_ttl(map
, &key
, TTL_MIN
);
257 /* If we had to open TTL file close it */
260 map
->ttl_path
= NULL
;
267 * FUNCTION: add_to_timeval()
269 * DESCRIPTION: Adds an int to a timeval
271 * NOTE : Seems strange that there is not a library function to do this
272 * if one exists then this function can be removed.
274 * NOTE : Does not handle UNIX clock wrap round but this is a much bigger
277 * INPUTS: Time value to add to
278 * Time value to add in seconds
280 * OUTPUTS: SUCCESS = Addition successful
281 * FAILURE = Addition failed (probably wrapped)
285 add_to_timeval(struct timeval
*t1
, int t2
)
287 struct timeval oldval
;
289 oldval
.tv_sec
= t1
->tv_sec
;
291 /* Add seconds part */
294 /* Check for clock wrap */
295 if (!(t1
->tv_sec
>= oldval
.tv_sec
)) {
296 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
297 "Wrap when adding %d to %d", t2
, oldval
.tv_sec
);
305 * FUNCTION: is_greater_timeval()
307 * DESCRIPTION: Compares two timevals
309 * NOTE : Seems strange that there is not a library function to do this
310 * if one exists then this function can be removed.
312 * INPUTS: First time value
313 * Time value to compare it with
315 * OUTPUTS: TRUE t1 > t2
320 is_greater_timeval(struct timeval
*t1
, struct timeval
*t2
)
322 if (t1
->tv_sec
> t2
->tv_sec
)
325 if (t1
->tv_sec
== t2
->tv_sec
) {
326 if (t1
->tv_usec
> t2
->tv_usec
)