xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/backover.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: backover.c,v 1.1.1.5 2014/05/28 09:58:46 tron Exp $	*/
2 
3 /* backover.c - backend overlay routines */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2003-2014 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 /* Functions to overlay other modules over a backend. */
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include <ac/string.h>
26 #include <ac/socket.h>
27 
28 #define SLAPD_TOOLS
29 #include "slap.h"
30 #include "config.h"
31 
32 static slap_overinst *overlays;
33 
34 static int
35 over_db_config(
36 	BackendDB *be,
37 	const char *fname,
38 	int lineno,
39 	int argc,
40 	char **argv
41 )
42 {
43 	slap_overinfo *oi = be->bd_info->bi_private;
44 	slap_overinst *on = oi->oi_list;
45 	BackendInfo *bi_orig = be->bd_info;
46 	struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
47 	ConfigArgs ca = {0};
48 	int rc = 0;
49 
50 	if ( oi->oi_orig->bi_db_config ) {
51 		be->bd_info = oi->oi_orig;
52 		be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
53 		rc = oi->oi_orig->bi_db_config( be, fname, lineno,
54 			argc, argv );
55 
56 		if ( be->bd_info != oi->oi_orig ) {
57 			slap_overinfo	*oi2;
58 			slap_overinst	*on2, **onp;
59 			BackendDB	be2 = *be;
60 			int		i;
61 
62 			/* a database added an overlay;
63 			 * work it around... */
64 			assert( overlay_is_over( be ) );
65 
66 			oi2 = ( slap_overinfo * )be->bd_info->bi_private;
67 			on2 = oi2->oi_list;
68 
69 			/* need to put a uniqueness check here as well;
70 			 * note that in principle there could be more than
71 			 * one overlay as a result of multiple calls to
72 			 * overlay_config() */
73 			be2.bd_info = (BackendInfo *)oi;
74 
75 			for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
76 				if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
77 					Debug( LDAP_DEBUG_ANY, "over_db_config(): "
78 							"warning, freshly added "
79 							"overlay #%d \"%s\" is already in list\n",
80 							i, (*onp)->on_bi.bi_type, 0 );
81 
82 					/* NOTE: if the overlay already exists,
83 					 * there is no way to merge the results
84 					 * of the configuration that may have
85 					 * occurred during bi_db_config(); we
86 					 * just issue a warning, and the
87 					 * administrator should deal with this */
88 				}
89 			}
90 			*onp = oi->oi_list;
91 
92 			oi->oi_list = on2;
93 
94 			ch_free( be->bd_info );
95 		}
96 
97 		be->bd_info = (BackendInfo *)oi;
98 		if ( rc != SLAP_CONF_UNKNOWN ) return rc;
99 	}
100 
101 	ca.argv = argv;
102 	ca.argc = argc;
103 	ca.fname = fname;
104 	ca.lineno = lineno;
105 	ca.be = be;
106 	snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
107 			ca.fname, ca.lineno );
108 	ca.op = SLAP_CONFIG_ADD;
109 	ca.valx = -1;
110 
111 	for (; on; on=on->on_next) {
112 		rc = SLAP_CONF_UNKNOWN;
113 		if (on->on_bi.bi_cf_ocs) {
114 			ConfigTable *ct;
115 			ca.bi = &on->on_bi;
116 			ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
117 			if ( ct ) {
118 				ca.table = on->on_bi.bi_cf_ocs->co_type;
119 				rc = config_add_vals( ct, &ca );
120 				if ( rc != SLAP_CONF_UNKNOWN )
121 					break;
122 			}
123 		}
124 		if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
125 			be->bd_info = &on->on_bi;
126 			rc = on->on_bi.bi_db_config( be, fname, lineno,
127 				argc, argv );
128 			if ( rc != SLAP_CONF_UNKNOWN ) break;
129 		}
130 	}
131 	be->bd_info = bi_orig;
132 	be->be_cf_ocs = be_cf_ocs;
133 
134 	return rc;
135 }
136 
137 static int
138 over_db_open(
139 	BackendDB *be,
140 	ConfigReply *cr
141 )
142 {
143 	slap_overinfo *oi = be->bd_info->bi_private;
144 	slap_overinst *on = oi->oi_list;
145 	BackendDB db = *be;
146 	int rc = 0;
147 
148 	db.be_flags |= SLAP_DBFLAG_OVERLAY;
149 	db.bd_info = oi->oi_orig;
150 	if ( db.bd_info->bi_db_open ) {
151 		rc = db.bd_info->bi_db_open( &db, cr );
152 	}
153 
154 	for (; on && rc == 0; on=on->on_next) {
155 		db.bd_info = &on->on_bi;
156 		if ( db.bd_info->bi_db_open ) {
157 			rc = db.bd_info->bi_db_open( &db, cr );
158 		}
159 	}
160 
161 	return rc;
162 }
163 
164 static int
165 over_db_close(
166 	BackendDB *be,
167 	ConfigReply *cr
168 )
169 {
170 	slap_overinfo *oi = be->bd_info->bi_private;
171 	slap_overinst *on = oi->oi_list;
172 	BackendInfo *bi_orig = be->bd_info;
173 	int rc = 0;
174 
175 	for (; on && rc == 0; on=on->on_next) {
176 		be->bd_info = &on->on_bi;
177 		if ( be->bd_info->bi_db_close ) {
178 			rc = be->bd_info->bi_db_close( be, cr );
179 		}
180 	}
181 
182 	if ( oi->oi_orig->bi_db_close ) {
183 		be->bd_info = oi->oi_orig;
184 		rc = be->bd_info->bi_db_close( be, cr );
185 	}
186 
187 	be->bd_info = bi_orig;
188 	return rc;
189 }
190 
191 static int
192 over_db_destroy(
193 	BackendDB *be,
194 	ConfigReply *cr
195 )
196 {
197 	slap_overinfo *oi = be->bd_info->bi_private;
198 	slap_overinst *on = oi->oi_list, *next;
199 	BackendInfo *bi_orig = be->bd_info;
200 	int rc = 0;
201 
202 	be->bd_info = oi->oi_orig;
203 	if ( be->bd_info->bi_db_destroy ) {
204 		rc = be->bd_info->bi_db_destroy( be, cr );
205 	}
206 
207 	for (; on && rc == 0; on=on->on_next) {
208 		be->bd_info = &on->on_bi;
209 		if ( be->bd_info->bi_db_destroy ) {
210 			rc = be->bd_info->bi_db_destroy( be, cr );
211 		}
212 	}
213 
214 	on = oi->oi_list;
215 	if ( on ) {
216 		for (next = on->on_next; on; on=next) {
217 			next = on->on_next;
218 			free( on );
219 		}
220 	}
221 	be->bd_info = bi_orig;
222 	free( oi );
223 	return rc;
224 }
225 
226 static int
227 over_back_response ( Operation *op, SlapReply *rs )
228 {
229 	slap_overinfo *oi = op->o_callback->sc_private;
230 	slap_overinst *on = oi->oi_list;
231 	int rc = SLAP_CB_CONTINUE;
232 	BackendDB *be = op->o_bd, db = *op->o_bd;
233 
234 	db.be_flags |= SLAP_DBFLAG_OVERLAY;
235 	op->o_bd = &db;
236 	for (; on; on=on->on_next ) {
237 		if ( on->on_response ) {
238 			db.bd_info = (BackendInfo *)on;
239 			rc = on->on_response( op, rs );
240 			if ( rc != SLAP_CB_CONTINUE ) break;
241 		}
242 	}
243 	/* Bypass the remaining on_response layers, but allow
244 	 * normal execution to continue.
245 	 */
246 	if ( rc == SLAP_CB_BYPASS )
247 		rc = SLAP_CB_CONTINUE;
248 	op->o_bd = be;
249 	return rc;
250 }
251 
252 static int
253 over_access_allowed(
254 	Operation		*op,
255 	Entry			*e,
256 	AttributeDescription	*desc,
257 	struct berval		*val,
258 	slap_access_t		access,
259 	AccessControlState	*state,
260 	slap_mask_t		*maskp )
261 {
262 	slap_overinfo *oi;
263 	slap_overinst *on;
264 	BackendInfo *bi;
265 	BackendDB *be = op->o_bd, db;
266 	int rc = SLAP_CB_CONTINUE;
267 
268 	/* FIXME: used to happen for instance during abandon
269 	 * when global overlays are used... */
270 	assert( op->o_bd != NULL );
271 
272 	bi = op->o_bd->bd_info;
273 	/* Were we invoked on the frontend? */
274 	if ( !bi->bi_access_allowed ) {
275 		oi = frontendDB->bd_info->bi_private;
276 	} else {
277 		oi = op->o_bd->bd_info->bi_private;
278 	}
279 	on = oi->oi_list;
280 
281 	for ( ; on; on = on->on_next ) {
282 		if ( on->on_bi.bi_access_allowed ) {
283 			/* NOTE: do not copy the structure until required */
284 		 	if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
285  				db = *op->o_bd;
286 				db.be_flags |= SLAP_DBFLAG_OVERLAY;
287 				op->o_bd = &db;
288 			}
289 
290 			op->o_bd->bd_info = (BackendInfo *)on;
291 			rc = on->on_bi.bi_access_allowed( op, e,
292 				desc, val, access, state, maskp );
293 			if ( rc != SLAP_CB_CONTINUE ) break;
294 		}
295 	}
296 
297 	if ( rc == SLAP_CB_CONTINUE ) {
298 		BI_access_allowed	*bi_access_allowed;
299 
300 		/* if the database structure was changed, o_bd points to a
301 		 * copy of the structure; put the original bd_info in place */
302 		if ( SLAP_ISOVERLAY( op->o_bd ) ) {
303 			op->o_bd->bd_info = oi->oi_orig;
304 		}
305 
306 		if ( oi->oi_orig->bi_access_allowed ) {
307 			bi_access_allowed = oi->oi_orig->bi_access_allowed;
308 		} else {
309 			bi_access_allowed = slap_access_allowed;
310 		}
311 
312 		rc = bi_access_allowed( op, e,
313 			desc, val, access, state, maskp );
314 	}
315 	/* should not fall thru this far without anything happening... */
316 	if ( rc == SLAP_CB_CONTINUE ) {
317 		/* access not allowed */
318 		rc = 0;
319 	}
320 
321 	op->o_bd = be;
322 	op->o_bd->bd_info = bi;
323 
324 	return rc;
325 }
326 
327 int
328 overlay_entry_get_ov(
329 	Operation		*op,
330 	struct berval	*dn,
331 	ObjectClass		*oc,
332 	AttributeDescription	*ad,
333 	int	rw,
334 	Entry	**e,
335 	slap_overinst *on )
336 {
337 	slap_overinfo *oi = on->on_info;
338 	BackendDB *be = op->o_bd, db;
339 	BackendInfo *bi = op->o_bd->bd_info;
340 	int rc = SLAP_CB_CONTINUE;
341 
342 	for ( ; on; on = on->on_next ) {
343 		if ( on->on_bi.bi_entry_get_rw ) {
344 			/* NOTE: do not copy the structure until required */
345 		 	if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
346  				db = *op->o_bd;
347 				db.be_flags |= SLAP_DBFLAG_OVERLAY;
348 				op->o_bd = &db;
349 			}
350 
351 			op->o_bd->bd_info = (BackendInfo *)on;
352 			rc = on->on_bi.bi_entry_get_rw( op, dn,
353 				oc, ad, rw, e );
354 			if ( rc != SLAP_CB_CONTINUE ) break;
355 		}
356 	}
357 
358 	if ( rc == SLAP_CB_CONTINUE ) {
359 		/* if the database structure was changed, o_bd points to a
360 		 * copy of the structure; put the original bd_info in place */
361 		if ( SLAP_ISOVERLAY( op->o_bd ) ) {
362 			op->o_bd->bd_info = oi->oi_orig;
363 		}
364 
365 		if ( oi->oi_orig->bi_entry_get_rw ) {
366 			rc = oi->oi_orig->bi_entry_get_rw( op, dn,
367 				oc, ad, rw, e );
368 		}
369 	}
370 	/* should not fall thru this far without anything happening... */
371 	if ( rc == SLAP_CB_CONTINUE ) {
372 		rc = LDAP_UNWILLING_TO_PERFORM;
373 	}
374 
375 	op->o_bd = be;
376 	op->o_bd->bd_info = bi;
377 
378 	return rc;
379 }
380 
381 static int
382 over_entry_get_rw(
383 	Operation		*op,
384 	struct berval	*dn,
385 	ObjectClass		*oc,
386 	AttributeDescription	*ad,
387 	int	rw,
388 	Entry	**e )
389 {
390 	slap_overinfo *oi;
391 	slap_overinst *on;
392 
393 	assert( op->o_bd != NULL );
394 
395 	oi = op->o_bd->bd_info->bi_private;
396 	on = oi->oi_list;
397 
398 	return overlay_entry_get_ov( op, dn, oc, ad, rw, e, on );
399 }
400 
401 int
402 overlay_entry_release_ov(
403 	Operation	*op,
404 	Entry	*e,
405 	int rw,
406 	slap_overinst *on )
407 {
408 	slap_overinfo *oi = on->on_info;
409 	BackendDB *be = op->o_bd, db;
410 	BackendInfo *bi = op->o_bd->bd_info;
411 	int rc = SLAP_CB_CONTINUE;
412 
413 	for ( ; on; on = on->on_next ) {
414 		if ( on->on_bi.bi_entry_release_rw ) {
415 			/* NOTE: do not copy the structure until required */
416 		 	if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
417  				db = *op->o_bd;
418 				db.be_flags |= SLAP_DBFLAG_OVERLAY;
419 				op->o_bd = &db;
420 			}
421 
422 			op->o_bd->bd_info = (BackendInfo *)on;
423 			rc = on->on_bi.bi_entry_release_rw( op, e, rw );
424 			if ( rc != SLAP_CB_CONTINUE ) break;
425 		}
426 	}
427 
428 	if ( rc == SLAP_CB_CONTINUE ) {
429 		/* if the database structure was changed, o_bd points to a
430 		 * copy of the structure; put the original bd_info in place */
431 		if ( SLAP_ISOVERLAY( op->o_bd ) ) {
432 			op->o_bd->bd_info = oi->oi_orig;
433 		}
434 
435 		if ( oi->oi_orig->bi_entry_release_rw ) {
436 			rc = oi->oi_orig->bi_entry_release_rw( op, e, rw );
437 		}
438 	}
439 	/* should not fall thru this far without anything happening... */
440 	if ( rc == SLAP_CB_CONTINUE ) {
441 		entry_free( e );
442 		rc = 0;
443 	}
444 
445 	op->o_bd = be;
446 	op->o_bd->bd_info = bi;
447 
448 	return rc;
449 }
450 
451 static int
452 over_entry_release_rw(
453 	Operation	*op,
454 	Entry	*e,
455 	int rw )
456 {
457 	slap_overinfo *oi;
458 	slap_overinst *on;
459 
460 	assert( op->o_bd != NULL );
461 
462 	oi = op->o_bd->bd_info->bi_private;
463 	on = oi->oi_list;
464 
465 	return overlay_entry_release_ov( op, e, rw, on );
466 }
467 
468 static int
469 over_acl_group(
470 	Operation		*op,
471 	Entry			*e,
472 	struct berval		*gr_ndn,
473 	struct berval		*op_ndn,
474 	ObjectClass		*group_oc,
475 	AttributeDescription	*group_at )
476 {
477 	slap_overinfo *oi;
478 	slap_overinst *on;
479 	BackendInfo *bi;
480 	BackendDB *be = op->o_bd, db;
481 	int rc = SLAP_CB_CONTINUE;
482 
483 	/* FIXME: used to happen for instance during abandon
484 	 * when global overlays are used... */
485 	assert( be != NULL );
486 
487 	bi = be->bd_info;
488 	oi = bi->bi_private;
489 	on = oi->oi_list;
490 
491 	for ( ; on; on = on->on_next ) {
492 		if ( on->on_bi.bi_acl_group ) {
493 			/* NOTE: do not copy the structure until required */
494 		 	if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
495  				db = *op->o_bd;
496 				db.be_flags |= SLAP_DBFLAG_OVERLAY;
497 				op->o_bd = &db;
498 			}
499 
500 			op->o_bd->bd_info = (BackendInfo *)on;
501 			rc = on->on_bi.bi_acl_group( op, e,
502 				gr_ndn, op_ndn, group_oc, group_at );
503 			if ( rc != SLAP_CB_CONTINUE ) break;
504 		}
505 	}
506 
507 	if ( rc == SLAP_CB_CONTINUE ) {
508 		BI_acl_group		*bi_acl_group;
509 
510 		/* if the database structure was changed, o_bd points to a
511 		 * copy of the structure; put the original bd_info in place */
512 		if ( SLAP_ISOVERLAY( op->o_bd ) ) {
513 			op->o_bd->bd_info = oi->oi_orig;
514 		}
515 
516 		if ( oi->oi_orig->bi_acl_group ) {
517 			bi_acl_group = oi->oi_orig->bi_acl_group;
518 		} else {
519 			bi_acl_group = backend_group;
520 		}
521 
522 		rc = bi_acl_group( op, e,
523 			gr_ndn, op_ndn, group_oc, group_at );
524 	}
525 	/* should not fall thru this far without anything happening... */
526 	if ( rc == SLAP_CB_CONTINUE ) {
527 		/* access not allowed */
528 		rc = 0;
529 	}
530 
531 	op->o_bd = be;
532 	op->o_bd->bd_info = bi;
533 
534 	return rc;
535 }
536 
537 static int
538 over_acl_attribute(
539 	Operation		*op,
540 	Entry			*target,
541 	struct berval		*entry_ndn,
542 	AttributeDescription	*entry_at,
543 	BerVarray		*vals,
544 	slap_access_t		access )
545 {
546 	slap_overinfo *oi;
547 	slap_overinst *on;
548 	BackendInfo *bi;
549 	BackendDB *be = op->o_bd, db;
550 	int rc = SLAP_CB_CONTINUE;
551 
552 	/* FIXME: used to happen for instance during abandon
553 	 * when global overlays are used... */
554 	assert( be != NULL );
555 
556 	bi = be->bd_info;
557 	oi = bi->bi_private;
558 	on = oi->oi_list;
559 
560 	for ( ; on; on = on->on_next ) {
561 		if ( on->on_bi.bi_acl_attribute ) {
562 			/* NOTE: do not copy the structure until required */
563 		 	if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
564  				db = *op->o_bd;
565 				db.be_flags |= SLAP_DBFLAG_OVERLAY;
566 				op->o_bd = &db;
567 			}
568 
569 			op->o_bd->bd_info = (BackendInfo *)on;
570 			rc = on->on_bi.bi_acl_attribute( op, target,
571 				entry_ndn, entry_at, vals, access );
572 			if ( rc != SLAP_CB_CONTINUE ) break;
573 		}
574 	}
575 
576 	if ( rc == SLAP_CB_CONTINUE ) {
577 		BI_acl_attribute		*bi_acl_attribute;
578 
579 		/* if the database structure was changed, o_bd points to a
580 		 * copy of the structure; put the original bd_info in place */
581 		if ( SLAP_ISOVERLAY( op->o_bd ) ) {
582 			op->o_bd->bd_info = oi->oi_orig;
583 		}
584 
585 		if ( oi->oi_orig->bi_acl_attribute ) {
586 			bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
587 		} else {
588 			bi_acl_attribute = backend_attribute;
589 		}
590 
591 		rc = bi_acl_attribute( op, target,
592 			entry_ndn, entry_at, vals, access );
593 	}
594 	/* should not fall thru this far without anything happening... */
595 	if ( rc == SLAP_CB_CONTINUE ) {
596 		/* access not allowed */
597 		rc = 0;
598 	}
599 
600 	op->o_bd = be;
601 	op->o_bd->bd_info = bi;
602 
603 	return rc;
604 }
605 
606 int
607 overlay_callback_after_backover( Operation *op, slap_callback *sc, int append )
608 {
609 	slap_callback **scp;
610 
611 	for ( scp = &op->o_callback; *scp != NULL; scp = &(*scp)->sc_next ) {
612 		if ( (*scp)->sc_response == over_back_response ) {
613 			sc->sc_next = (*scp)->sc_next;
614 			(*scp)->sc_next = sc;
615 			return 0;
616 		}
617 	}
618 
619 	if ( append ) {
620 		*scp = sc;
621 		return 0;
622 	}
623 
624 	return 1;
625 }
626 
627 /*
628  * default return code in case of missing backend function
629  * and overlay stack returning SLAP_CB_CONTINUE
630  */
631 static int op_rc[ op_last ] = {
632 	LDAP_UNWILLING_TO_PERFORM,	/* bind */
633 	LDAP_UNWILLING_TO_PERFORM,	/* unbind */
634 	LDAP_UNWILLING_TO_PERFORM,	/* search */
635 	SLAP_CB_CONTINUE,		/* compare; pass to frontend */
636 	LDAP_UNWILLING_TO_PERFORM,	/* modify */
637 	LDAP_UNWILLING_TO_PERFORM,	/* modrdn */
638 	LDAP_UNWILLING_TO_PERFORM,	/* add */
639 	LDAP_UNWILLING_TO_PERFORM,	/* delete */
640 	LDAP_UNWILLING_TO_PERFORM,	/* abandon */
641 	LDAP_UNWILLING_TO_PERFORM,	/* cancel */
642 	LDAP_UNWILLING_TO_PERFORM,	/* extended */
643 	LDAP_SUCCESS,			/* aux_operational */
644 	LDAP_SUCCESS,			/* aux_chk_referrals */
645 	SLAP_CB_CONTINUE		/* aux_chk_controls; pass to frontend */
646 };
647 
648 int overlay_op_walk(
649 	Operation *op,
650 	SlapReply *rs,
651 	slap_operation_t which,
652 	slap_overinfo *oi,
653 	slap_overinst *on
654 )
655 {
656 	BI_op_bind **func;
657 	int rc = SLAP_CB_CONTINUE;
658 
659 	for (; on; on=on->on_next ) {
660 		func = &on->on_bi.bi_op_bind;
661 		if ( func[which] ) {
662 			op->o_bd->bd_info = (BackendInfo *)on;
663 			rc = func[which]( op, rs );
664 			if ( rc != SLAP_CB_CONTINUE ) break;
665 		}
666 	}
667 	if ( rc == SLAP_CB_BYPASS )
668 		rc = SLAP_CB_CONTINUE;
669 
670 	func = &oi->oi_orig->bi_op_bind;
671 	if ( func[which] && rc == SLAP_CB_CONTINUE ) {
672 		op->o_bd->bd_info = oi->oi_orig;
673 		rc = func[which]( op, rs );
674 	}
675 	/* should not fall thru this far without anything happening... */
676 	if ( rc == SLAP_CB_CONTINUE ) {
677 		rc = op_rc[ which ];
678 	}
679 
680 	/* The underlying backend didn't handle the request, make sure
681 	 * overlay cleanup is processed.
682 	 */
683 	if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
684 		slap_callback *sc_next;
685 		for ( ; op->o_callback && op->o_callback->sc_response !=
686 			over_back_response; op->o_callback = sc_next ) {
687 			sc_next = op->o_callback->sc_next;
688 			if ( op->o_callback->sc_cleanup ) {
689 				op->o_callback->sc_cleanup( op, rs );
690 			}
691 		}
692 	}
693 	return rc;
694 }
695 
696 static int
697 over_op_func(
698 	Operation *op,
699 	SlapReply *rs,
700 	slap_operation_t which
701 )
702 {
703 	slap_overinfo *oi;
704 	slap_overinst *on;
705 	BackendDB *be = op->o_bd, db;
706 	slap_callback cb = {NULL, over_back_response, NULL, NULL}, **sc;
707 	int rc = SLAP_CB_CONTINUE;
708 
709 	/* FIXME: used to happen for instance during abandon
710 	 * when global overlays are used... */
711 	assert( op->o_bd != NULL );
712 
713 	oi = op->o_bd->bd_info->bi_private;
714 	on = oi->oi_list;
715 
716  	if ( !SLAP_ISOVERLAY( op->o_bd )) {
717  		db = *op->o_bd;
718 		db.be_flags |= SLAP_DBFLAG_OVERLAY;
719 		op->o_bd = &db;
720 	}
721 	cb.sc_next = op->o_callback;
722 	cb.sc_private = oi;
723 	op->o_callback = &cb;
724 
725 	rc = overlay_op_walk( op, rs, which, oi, on );
726 	for ( sc = &op->o_callback; *sc; sc = &(*sc)->sc_next ) {
727 		if ( *sc == &cb ) {
728 			*sc = cb.sc_next;
729 			break;
730 		}
731 	}
732 
733 	op->o_bd = be;
734 	return rc;
735 }
736 
737 static int
738 over_op_bind( Operation *op, SlapReply *rs )
739 {
740 	return over_op_func( op, rs, op_bind );
741 }
742 
743 static int
744 over_op_unbind( Operation *op, SlapReply *rs )
745 {
746 	return over_op_func( op, rs, op_unbind );
747 }
748 
749 static int
750 over_op_search( Operation *op, SlapReply *rs )
751 {
752 	return over_op_func( op, rs, op_search );
753 }
754 
755 static int
756 over_op_compare( Operation *op, SlapReply *rs )
757 {
758 	return over_op_func( op, rs, op_compare );
759 }
760 
761 static int
762 over_op_modify( Operation *op, SlapReply *rs )
763 {
764 	return over_op_func( op, rs, op_modify );
765 }
766 
767 static int
768 over_op_modrdn( Operation *op, SlapReply *rs )
769 {
770 	return over_op_func( op, rs, op_modrdn );
771 }
772 
773 static int
774 over_op_add( Operation *op, SlapReply *rs )
775 {
776 	return over_op_func( op, rs, op_add );
777 }
778 
779 static int
780 over_op_delete( Operation *op, SlapReply *rs )
781 {
782 	return over_op_func( op, rs, op_delete );
783 }
784 
785 static int
786 over_op_abandon( Operation *op, SlapReply *rs )
787 {
788 	return over_op_func( op, rs, op_abandon );
789 }
790 
791 static int
792 over_op_cancel( Operation *op, SlapReply *rs )
793 {
794 	return over_op_func( op, rs, op_cancel );
795 }
796 
797 static int
798 over_op_extended( Operation *op, SlapReply *rs )
799 {
800 	return over_op_func( op, rs, op_extended );
801 }
802 
803 static int
804 over_aux_operational( Operation *op, SlapReply *rs )
805 {
806 	return over_op_func( op, rs, op_aux_operational );
807 }
808 
809 static int
810 over_aux_chk_referrals( Operation *op, SlapReply *rs )
811 {
812 	return over_op_func( op, rs, op_aux_chk_referrals );
813 }
814 
815 static int
816 over_aux_chk_controls( Operation *op, SlapReply *rs )
817 {
818 	return over_op_func( op, rs, op_aux_chk_controls );
819 }
820 
821 enum conn_which {
822 	conn_init = 0,
823 	conn_destroy,
824 	conn_last
825 };
826 
827 static int
828 over_connection_func(
829 	BackendDB	*bd,
830 	Connection	*conn,
831 	enum conn_which	which
832 )
833 {
834 	slap_overinfo		*oi;
835 	slap_overinst		*on;
836 	BackendDB		db;
837 	int			rc = SLAP_CB_CONTINUE;
838 	BI_connection_init	**func;
839 
840 	/* FIXME: used to happen for instance during abandon
841 	 * when global overlays are used... */
842 	assert( bd != NULL );
843 
844 	oi = bd->bd_info->bi_private;
845 	on = oi->oi_list;
846 
847  	if ( !SLAP_ISOVERLAY( bd ) ) {
848  		db = *bd;
849 		db.be_flags |= SLAP_DBFLAG_OVERLAY;
850 		bd = &db;
851 	}
852 
853 	for ( ; on; on = on->on_next ) {
854 		func = &on->on_bi.bi_connection_init;
855 		if ( func[ which ] ) {
856 			bd->bd_info = (BackendInfo *)on;
857 			rc = func[ which ]( bd, conn );
858 			if ( rc != SLAP_CB_CONTINUE ) break;
859 		}
860 	}
861 
862 	func = &oi->oi_orig->bi_connection_init;
863 	if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
864 		bd->bd_info = oi->oi_orig;
865 		rc = func[ which ]( bd, conn );
866 	}
867 	/* should not fall thru this far without anything happening... */
868 	if ( rc == SLAP_CB_CONTINUE ) {
869 		rc = LDAP_UNWILLING_TO_PERFORM;
870 	}
871 
872 	return rc;
873 }
874 
875 static int
876 over_connection_init(
877 	BackendDB	*bd,
878 	Connection	*conn
879 )
880 {
881 	return over_connection_func( bd, conn, conn_init );
882 }
883 
884 static int
885 over_connection_destroy(
886 	BackendDB	*bd,
887 	Connection	*conn
888 )
889 {
890 	return over_connection_func( bd, conn, conn_destroy );
891 }
892 
893 int
894 overlay_register(
895 	slap_overinst *on
896 )
897 {
898 	slap_overinst	*tmp;
899 
900 	/* FIXME: check for duplicates? */
901 	for ( tmp = overlays; tmp != NULL; tmp = tmp->on_next ) {
902 		if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_type ) == 0 ) {
903 			Debug( LDAP_DEBUG_ANY,
904 				"overlay_register(\"%s\"): "
905 				"name already in use.\n",
906 				on->on_bi.bi_type, 0, 0 );
907 			return -1;
908 		}
909 
910 		if ( on->on_bi.bi_obsolete_names != NULL ) {
911 			int	i;
912 
913 			for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
914 				if ( strcmp( on->on_bi.bi_obsolete_names[ i ], tmp->on_bi.bi_type ) == 0 ) {
915 					Debug( LDAP_DEBUG_ANY,
916 						"overlay_register(\"%s\"): "
917 						"obsolete name \"%s\" already in use "
918 						"by overlay \"%s\".\n",
919 						on->on_bi.bi_type,
920 						on->on_bi.bi_obsolete_names[ i ],
921 						tmp->on_bi.bi_type );
922 					return -1;
923 				}
924 			}
925 		}
926 
927 		if ( tmp->on_bi.bi_obsolete_names != NULL ) {
928 			int	i;
929 
930 			for ( i = 0; tmp->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
931 				int	j;
932 
933 				if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
934 					Debug( LDAP_DEBUG_ANY,
935 						"overlay_register(\"%s\"): "
936 						"name already in use "
937 						"as obsolete by overlay \"%s\".\n",
938 						on->on_bi.bi_type,
939 						tmp->on_bi.bi_obsolete_names[ i ], 0 );
940 					return -1;
941 				}
942 
943 				if ( on->on_bi.bi_obsolete_names != NULL ) {
944 					for ( j = 0; on->on_bi.bi_obsolete_names[ j ] != NULL; j++ ) {
945 						if ( strcmp( on->on_bi.bi_obsolete_names[ j ], tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
946 							Debug( LDAP_DEBUG_ANY,
947 								"overlay_register(\"%s\"): "
948 								"obsolete name \"%s\" already in use "
949 								"as obsolete by overlay \"%s\".\n",
950 								on->on_bi.bi_type,
951 								on->on_bi.bi_obsolete_names[ j ],
952 								tmp->on_bi.bi_type );
953 							return -1;
954 						}
955 					}
956 				}
957 			}
958 		}
959 	}
960 
961 	on->on_next = overlays;
962 	overlays = on;
963 	return 0;
964 }
965 
966 /*
967  * iterator on registered overlays; overlay_next( NULL ) returns the first
968  * overlay; subsequent calls with the previously returned value allow to
969  * iterate over the entire list; returns NULL when no more overlays are
970  * registered.
971  */
972 
973 slap_overinst *
974 overlay_next(
975 	slap_overinst *on
976 )
977 {
978 	if ( on == NULL ) {
979 		return overlays;
980 	}
981 
982 	return on->on_next;
983 }
984 
985 /*
986  * returns a specific registered overlay based on the type; NULL if not
987  * registered.
988  */
989 
990 slap_overinst *
991 overlay_find( const char *over_type )
992 {
993 	slap_overinst *on = overlays;
994 
995 	assert( over_type != NULL );
996 
997 	for ( ; on; on = on->on_next ) {
998 		if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
999 			goto foundit;
1000 		}
1001 
1002 		if ( on->on_bi.bi_obsolete_names != NULL ) {
1003 			int	i;
1004 
1005 			for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
1006 				if ( strcmp( on->on_bi.bi_obsolete_names[ i ], over_type ) == 0 ) {
1007 					Debug( LDAP_DEBUG_ANY,
1008 						"overlay_find(\"%s\"): "
1009 						"obsolete name for \"%s\".\n",
1010 						on->on_bi.bi_obsolete_names[ i ],
1011 						on->on_bi.bi_type, 0 );
1012 					goto foundit;
1013 				}
1014 			}
1015 		}
1016 	}
1017 
1018 foundit:;
1019 	return on;
1020 }
1021 
1022 static const char overtype[] = "over";
1023 
1024 /*
1025  * returns TRUE (1) if the database is actually an overlay instance;
1026  * FALSE (0) otherwise.
1027  */
1028 
1029 int
1030 overlay_is_over( BackendDB *be )
1031 {
1032 	return be->bd_info->bi_type == overtype;
1033 }
1034 
1035 /*
1036  * returns TRUE (1) if the given database is actually an overlay
1037  * instance and, somewhere in the list, contains the requested overlay;
1038  * FALSE (0) otherwise.
1039  */
1040 
1041 int
1042 overlay_is_inst( BackendDB *be, const char *over_type )
1043 {
1044 	slap_overinst	*on;
1045 
1046 	assert( be != NULL );
1047 
1048 	if ( !overlay_is_over( be ) ) {
1049 		return 0;
1050 	}
1051 
1052 	on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
1053 	for ( ; on; on = on->on_next ) {
1054 		if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
1055 			return 1;
1056 		}
1057 	}
1058 
1059 	return 0;
1060 }
1061 
1062 int
1063 overlay_register_control( BackendDB *be, const char *oid )
1064 {
1065 	int		gotit = 0;
1066 	int		cid;
1067 
1068 	if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
1069 		return -1;
1070 	}
1071 
1072 	if ( SLAP_ISGLOBALOVERLAY( be ) ) {
1073 		BackendDB *bd;
1074 
1075 		/* add to all backends... */
1076 		LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
1077 			if ( bd == be->bd_self ) {
1078 				gotit = 1;
1079 			}
1080 
1081 			/* overlays can be instanciated multiple times, use
1082 			 * be_ctrls[ cid ] as an instance counter, so that the
1083 			 * overlay's controls are only really disabled after the
1084 			 * last instance called overlay_register_control() */
1085 			bd->be_ctrls[ cid ]++;
1086 			bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1087 		}
1088 
1089 	}
1090 
1091 	if ( !gotit ) {
1092 		/* overlays can be instanciated multiple times, use
1093 		 * be_ctrls[ cid ] as an instance counter, so that the
1094 		 * overlay's controls are only really unregistered after the
1095 		 * last instance called overlay_register_control() */
1096 		be->bd_self->be_ctrls[ cid ]++;
1097 		be->bd_self->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1098 	}
1099 
1100 	return 0;
1101 }
1102 
1103 #ifdef SLAP_CONFIG_DELETE
1104 void
1105 overlay_unregister_control( BackendDB *be, const char *oid )
1106 {
1107 	int		gotit = 0;
1108 	int		cid;
1109 
1110 	if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
1111 		return;
1112 	}
1113 
1114 	if ( SLAP_ISGLOBALOVERLAY( be ) ) {
1115 		BackendDB *bd;
1116 
1117 		/* remove from all backends... */
1118 		LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
1119 			if ( bd == be->bd_self ) {
1120 				gotit = 1;
1121 			}
1122 
1123 			bd->be_ctrls[ cid ]--;
1124 		}
1125 	}
1126 
1127 	if ( !gotit ) {
1128 		be->bd_self->be_ctrls[ cid ]--;
1129 	}
1130 }
1131 #endif /* SLAP_CONFIG_DELETE */
1132 
1133 void
1134 overlay_destroy_one( BackendDB *be, slap_overinst *on )
1135 {
1136 	slap_overinfo *oi = on->on_info;
1137 	slap_overinst **oidx;
1138 
1139 	for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
1140 		if ( *oidx == on ) {
1141 			*oidx = on->on_next;
1142 			if ( on->on_bi.bi_db_destroy ) {
1143 				BackendInfo *bi_orig = be->bd_info;
1144 				be->bd_info = (BackendInfo *)on;
1145 				on->on_bi.bi_db_destroy( be, NULL );
1146 				be->bd_info = bi_orig;
1147 			}
1148 			free( on );
1149 			break;
1150 		}
1151 	}
1152 }
1153 
1154 #ifdef SLAP_CONFIG_DELETE
1155 typedef struct ov_remove_ctx {
1156 	BackendDB *be;
1157 	slap_overinst *on;
1158 } ov_remove_ctx;
1159 
1160 int
1161 overlay_remove_cb( Operation *op, SlapReply *rs )
1162 {
1163 	ov_remove_ctx *rm_ctx = (ov_remove_ctx*) op->o_callback->sc_private;
1164 	BackendInfo *bi_orig = rm_ctx->be->bd_info;
1165 
1166 	rm_ctx->be->bd_info = (BackendInfo*) rm_ctx->on;
1167 
1168 	if ( rm_ctx->on->on_bi.bi_db_close ) {
1169 		rm_ctx->on->on_bi.bi_db_close( rm_ctx->be, NULL );
1170 	}
1171 	if ( rm_ctx->on->on_bi.bi_db_destroy ) {
1172 		rm_ctx->on->on_bi.bi_db_destroy( rm_ctx->be, NULL );
1173 	}
1174 
1175 	/* clean up after removing last overlay */
1176 	if ( ! rm_ctx->on->on_info->oi_list ) {
1177 		/* reset db flags and bd_info to orig */
1178 		SLAP_DBFLAGS( rm_ctx->be ) &= ~SLAP_DBFLAG_GLOBAL_OVERLAY;
1179 		rm_ctx->be->bd_info = rm_ctx->on->on_info->oi_orig;
1180 		ch_free(rm_ctx->on->on_info);
1181 	} else {
1182 		rm_ctx->be->bd_info = bi_orig;
1183 	}
1184 	free( rm_ctx->on );
1185 	op->o_tmpfree(rm_ctx, op->o_tmpmemctx);
1186 	return SLAP_CB_CONTINUE;
1187 }
1188 
1189 void
1190 overlay_remove( BackendDB *be, slap_overinst *on, Operation *op )
1191 {
1192 	slap_overinfo *oi = on->on_info;
1193 	slap_overinst **oidx;
1194 	ov_remove_ctx *rm_ctx;
1195 	slap_callback *rm_cb, *cb;
1196 
1197 	/* remove overlay from oi_list */
1198 	for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
1199 		if ( *oidx == on ) {
1200 			*oidx = on->on_next;
1201 			break;
1202 		}
1203 	}
1204 
1205 	/* The db_close and db_destroy handlers to cleanup a release
1206 	 * the overlay's resources are called from the cleanup callback
1207 	 */
1208 	rm_ctx = op->o_tmpalloc( sizeof( ov_remove_ctx ), op->o_tmpmemctx );
1209 	rm_ctx->be = be;
1210 	rm_ctx->on = on;
1211 
1212 	rm_cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx );
1213 	rm_cb->sc_next = NULL;
1214 	rm_cb->sc_cleanup = overlay_remove_cb;
1215 	rm_cb->sc_response = NULL;
1216 	rm_cb->sc_private = (void*) rm_ctx;
1217 
1218 	/* Append callback to the end of the list */
1219 	if ( !op->o_callback ) {
1220 		op->o_callback = rm_cb;
1221 	} else {
1222 		for ( cb = op->o_callback; cb->sc_next; cb = cb->sc_next );
1223 		cb->sc_next = rm_cb;
1224 	}
1225 }
1226 #endif /* SLAP_CONFIG_DELETE */
1227 
1228 void
1229 overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
1230 	int idx )
1231 {
1232 	slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1233 
1234 	if ( idx == -1 ) {
1235 		on2->on_next = oi->oi_list;
1236 		oi->oi_list = on2;
1237 	} else {
1238 		int i, novs;
1239 		slap_overinst *on, **prev;
1240 
1241 		/* Since the list is in reverse order and is singly linked,
1242 		 * we have to count the overlays and then insert backwards.
1243 		 * Adding on overlay at a specific point should be a pretty
1244 		 * infrequent occurrence.
1245 		 */
1246 		novs = 0;
1247 		for ( on = oi->oi_list; on; on=on->on_next )
1248 			novs++;
1249 
1250 		if (idx > novs)
1251 			idx = 0;
1252 		else
1253 			idx = novs - idx;
1254 
1255 		/* advance to insertion point */
1256 		prev = &oi->oi_list;
1257 		for ( i=0; i<idx; i++ ) {
1258 			on = *prev;
1259 			prev = &on->on_next;
1260 		}
1261 		/* insert */
1262 		on2->on_next = *prev;
1263 		*prev = on2;
1264 	}
1265 }
1266 
1267 void
1268 overlay_move( BackendDB *be, slap_overinst *on, int idx )
1269 {
1270 	slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1271 	slap_overinst **onp;
1272 
1273 	for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
1274 		if ( *onp == on ) {
1275 			*onp = on->on_next;
1276 			break;
1277 		}
1278 	}
1279 	overlay_insert( be, on, &onp, idx );
1280 }
1281 
1282 /* add an overlay to a particular backend. */
1283 int
1284 overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res, ConfigReply *cr )
1285 {
1286 	slap_overinst *on = NULL, *on2 = NULL, **prev;
1287 	slap_overinfo *oi = NULL;
1288 	BackendInfo *bi = NULL;
1289 
1290 	if ( res )
1291 		*res = NULL;
1292 
1293 	on = overlay_find( ov );
1294 	if ( !on ) {
1295 		Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
1296 		return 1;
1297 	}
1298 
1299 	/* If this is the first overlay on this backend, set up the
1300 	 * overlay info structure
1301 	 */
1302 	if ( !overlay_is_over( be ) ) {
1303 		int	isglobal = 0;
1304 
1305 		/* NOTE: the first time a global overlay is configured,
1306 		 * frontendDB gets this flag; it is used later by overlays
1307 		 * to determine if they're stacked on top of the frontendDB */
1308 		if ( be->bd_info == frontendDB->bd_info || SLAP_ISGLOBALOVERLAY( be ) ) {
1309 			isglobal = 1;
1310 			if ( on->on_bi.bi_flags & SLAPO_BFLAG_DBONLY ) {
1311 				Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1312 					"overlay \"%s\" cannot be global.\n",
1313 					ov, 0, 0 );
1314 				return 1;
1315 			}
1316 
1317 		} else if ( on->on_bi.bi_flags & SLAPO_BFLAG_GLOBONLY ) {
1318 			Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1319 				"overlay \"%s\" can only be global.\n",
1320 				ov, 0, 0 );
1321 			return 1;
1322 		}
1323 
1324 		oi = ch_malloc( sizeof( slap_overinfo ) );
1325 		oi->oi_orig = be->bd_info;
1326 		oi->oi_bi = *be->bd_info;
1327 		oi->oi_origdb = be;
1328 
1329 		if ( isglobal ) {
1330 			SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
1331 		}
1332 
1333 		/* Save a pointer to ourself in bi_private.
1334 		 */
1335 		oi->oi_bi.bi_private = oi;
1336 		oi->oi_list = NULL;
1337 		bi = (BackendInfo *)oi;
1338 
1339 		bi->bi_type = (char *)overtype;
1340 
1341 		bi->bi_db_config = over_db_config;
1342 		bi->bi_db_open = over_db_open;
1343 		bi->bi_db_close = over_db_close;
1344 		bi->bi_db_destroy = over_db_destroy;
1345 
1346 		bi->bi_op_bind = over_op_bind;
1347 		bi->bi_op_unbind = over_op_unbind;
1348 		bi->bi_op_search = over_op_search;
1349 		bi->bi_op_compare = over_op_compare;
1350 		bi->bi_op_modify = over_op_modify;
1351 		bi->bi_op_modrdn = over_op_modrdn;
1352 		bi->bi_op_add = over_op_add;
1353 		bi->bi_op_delete = over_op_delete;
1354 		bi->bi_op_abandon = over_op_abandon;
1355 		bi->bi_op_cancel = over_op_cancel;
1356 
1357 		bi->bi_extended = over_op_extended;
1358 
1359 		/*
1360 		 * this is fine because it has the same
1361 		 * args of the operations; we need to rework
1362 		 * all the hooks to share the same args
1363 		 * of the operations...
1364 		 */
1365 		bi->bi_operational = over_aux_operational;
1366 		bi->bi_chk_referrals = over_aux_chk_referrals;
1367 		bi->bi_chk_controls = over_aux_chk_controls;
1368 
1369 		/* these have specific arglists */
1370 		bi->bi_entry_get_rw = over_entry_get_rw;
1371 		bi->bi_entry_release_rw = over_entry_release_rw;
1372 		bi->bi_access_allowed = over_access_allowed;
1373 		bi->bi_acl_group = over_acl_group;
1374 		bi->bi_acl_attribute = over_acl_attribute;
1375 
1376 		bi->bi_connection_init = over_connection_init;
1377 		bi->bi_connection_destroy = over_connection_destroy;
1378 
1379 		be->bd_info = bi;
1380 
1381 	} else {
1382 		if ( overlay_is_inst( be, ov ) ) {
1383 			if ( SLAPO_SINGLE( be ) ) {
1384 				Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1385 					"overlay \"%s\" already in list\n",
1386 					ov, 0, 0 );
1387 				return 1;
1388 			}
1389 		}
1390 
1391 		oi = be->bd_info->bi_private;
1392 	}
1393 
1394 	/* Insert new overlay into list. By default overlays are
1395 	 * added to head of list and executed in LIFO order.
1396 	 */
1397 	on2 = ch_calloc( 1, sizeof(slap_overinst) );
1398 	*on2 = *on;
1399 	on2->on_info = oi;
1400 
1401 	prev = &oi->oi_list;
1402 	/* Do we need to find the insertion point? */
1403 	if ( idx >= 0 ) {
1404 		int i;
1405 
1406 		/* count current overlays */
1407 		for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
1408 
1409 		/* are we just appending a new one? */
1410 		if ( idx >= i )
1411 			idx = -1;
1412 	}
1413 	overlay_insert( be, on2, &prev, idx );
1414 
1415 	/* Any initialization needed? */
1416 	if ( on2->on_bi.bi_db_init ) {
1417 		int rc;
1418 		be->bd_info = (BackendInfo *)on2;
1419 		rc = on2->on_bi.bi_db_init( be, cr);
1420 		be->bd_info = (BackendInfo *)oi;
1421 		if ( rc ) {
1422 			*prev = on2->on_next;
1423 			ch_free( on2 );
1424 			on2 = NULL;
1425 			return rc;
1426 		}
1427 	}
1428 
1429 	if ( res )
1430 		*res = &on2->on_bi;
1431 
1432 	return 0;
1433 }
1434 
1435