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