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