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