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