]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
5585f9a2ff4c49b9861d5cebae956cad3c318dd9
[openldap] / servers / slapd / backover.c
1 /* backover.c - backend overlay routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2006 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 enum db_which {
33         db_open = 0,
34         db_close,
35         db_destroy,
36         db_last
37 };
38
39 static int
40 over_db_func(
41         BackendDB *be,
42         enum db_which which
43 )
44 {
45         slap_overinfo *oi = be->bd_info->bi_private;
46         slap_overinst *on = oi->oi_list;
47         BackendInfo *bi_orig = be->bd_info;
48         BI_db_open **func;
49         int rc = 0;
50
51         func = &oi->oi_orig->bi_db_open;
52         if ( func[which] ) {
53                 be->bd_info = oi->oi_orig;
54                 rc = func[which]( be );
55         }
56
57         for (; on && rc == 0; on=on->on_next) {
58                 be->bd_info = &on->on_bi;
59                 func = &on->on_bi.bi_db_open;
60                 if (func[which]) {
61                         rc = func[which]( be );
62                 }
63         }
64         be->bd_info = bi_orig;
65         return rc;
66 }
67
68 static int
69 over_db_config(
70         BackendDB *be,
71         const char *fname,
72         int lineno,
73         int argc,
74         char **argv
75 )
76 {
77         slap_overinfo *oi = be->bd_info->bi_private;
78         slap_overinst *on = oi->oi_list;
79         BackendInfo *bi_orig = be->bd_info;
80         struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
81         ConfigArgs ca = {0};
82         int rc = 0;
83
84         if ( oi->oi_orig->bi_db_config ) {
85                 be->bd_info = oi->oi_orig;
86                 be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
87                 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
88                         argc, argv );
89
90                 if ( be->bd_info != oi->oi_orig ) {
91                         slap_overinfo   *oi2;
92                         slap_overinst   *on2, **onp;
93                         BackendDB       be2 = *be;
94                         int             i;
95
96                         /* a database added an overlay;
97                          * work it around... */
98                         assert( overlay_is_over( be ) );
99                         
100                         oi2 = ( slap_overinfo * )be->bd_info->bi_private;
101                         on2 = oi2->oi_list;
102
103                         /* need to put a uniqueness check here as well;
104                          * note that in principle there could be more than
105                          * one overlay as a result of multiple calls to
106                          * overlay_config() */
107                         be2.bd_info = (BackendInfo *)oi;
108
109                         for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
110                                 if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
111                                         Debug( LDAP_DEBUG_ANY, "over_db_config(): "
112                                                         "warning, freshly added "
113                                                         "overlay #%d \"%s\" is already in list\n",
114                                                         i, (*onp)->on_bi.bi_type, 0 );
115
116                                         /* NOTE: if the overlay already exists,
117                                          * there is no way to merge the results
118                                          * of the configuration that may have 
119                                          * occurred during bi_db_config(); we
120                                          * just issue a warning, and the 
121                                          * administrator should deal with this */
122                                 }
123                         }
124                         *onp = oi->oi_list;
125
126                         oi->oi_list = on2;
127
128                         ch_free( be->bd_info );
129                 }
130
131                 be->bd_info = (BackendInfo *)oi;
132                 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
133         }
134
135         ca.argv = argv;
136         ca.argc = argc;
137         ca.fname = fname;
138         ca.lineno = lineno;
139         ca.be = be;
140         snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
141                         ca.fname, ca.lineno );
142
143         for (; on; on=on->on_next) {
144                 rc = SLAP_CONF_UNKNOWN;
145                 if (on->on_bi.bi_cf_ocs) {
146                         ConfigTable *ct;
147                         ca.bi = &on->on_bi;
148                         ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
149                         if ( ct ) {
150                                 rc = config_add_vals( ct, &ca );
151                                 if ( rc != SLAP_CONF_UNKNOWN )
152                                         break;
153                         }
154                 }
155                 if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
156                         be->bd_info = &on->on_bi;
157                         rc = on->on_bi.bi_db_config( be, fname, lineno,
158                                 argc, argv );
159                         if ( rc != SLAP_CONF_UNKNOWN ) break;
160                 }
161         }
162         be->bd_info = bi_orig;
163         be->be_cf_ocs = be_cf_ocs;
164         
165         return rc;
166 }
167
168 static int
169 over_db_open(
170         BackendDB *be
171 )
172 {
173         return over_db_func( be, db_open );
174 }
175
176 static int
177 over_db_close(
178         BackendDB *be
179 )
180 {
181         slap_overinfo *oi = be->bd_info->bi_private;
182         slap_overinst *on = oi->oi_list;
183         BackendInfo *bi_orig = be->bd_info;
184         int rc = 0;
185
186         for (; on && rc == 0; on=on->on_next) {
187                 be->bd_info = &on->on_bi;
188                 if ( be->bd_info->bi_db_close ) {
189                         rc = be->bd_info->bi_db_close( be );
190                 }
191         }
192
193         if ( oi->oi_orig->bi_db_close ) {
194                 be->bd_info = oi->oi_orig;
195                 rc = be->bd_info->bi_db_close( be );
196         }
197
198         be->bd_info = bi_orig;
199         return rc;
200 }
201
202 static int
203 over_db_destroy(
204         BackendDB *be
205 )
206 {
207         slap_overinfo *oi = be->bd_info->bi_private;
208         slap_overinst *on = oi->oi_list, *next;
209         int rc;
210
211         rc = over_db_func( be, db_destroy );
212
213         for (next = on->on_next; on; on=next) {
214                 next = on->on_next;
215                 free( on );
216         }
217         free( oi );
218         return rc;
219 }
220
221 static int
222 over_back_response ( Operation *op, SlapReply *rs )
223 {
224         slap_overinfo *oi = op->o_callback->sc_private;
225         slap_overinst *on = oi->oi_list;
226         int rc = SLAP_CB_CONTINUE;
227         BackendDB *be = op->o_bd, db = *op->o_bd;
228
229         db.be_flags |= SLAP_DBFLAG_OVERLAY;
230         op->o_bd = &db;
231         for (; on; on=on->on_next ) {
232                 if ( on->on_response ) {
233                         db.bd_info = (BackendInfo *)on;
234                         rc = on->on_response( op, rs );
235                         if ( rc != SLAP_CB_CONTINUE ) break;
236                 }
237         }
238         op->o_bd = be;
239         return rc;
240 }
241
242 #ifdef SLAP_OVERLAY_ACCESS
243 static int
244 over_access_allowed(
245         Operation               *op,
246         Entry                   *e,
247         AttributeDescription    *desc,
248         struct berval           *val,
249         slap_access_t           access,
250         AccessControlState      *state,
251         slap_mask_t             *maskp )
252 {
253         slap_overinfo *oi;
254         slap_overinst *on;
255         BackendInfo *bi;
256         BackendDB *be = op->o_bd, db;
257         int rc = SLAP_CB_CONTINUE;
258
259         /* FIXME: used to happen for instance during abandon
260          * when global overlays are used... */
261         assert( op->o_bd != NULL );
262
263         bi = op->o_bd->bd_info;
264         /* Were we invoked on the frontend? */
265         if ( !bi->bi_access_allowed ) {
266                 oi = frontendDB->bd_info->bi_private;
267         } else {
268                 oi = op->o_bd->bd_info->bi_private;
269         }
270         on = oi->oi_list;
271
272         for ( ; on; on = on->on_next ) {
273                 if ( on->on_bi.bi_access_allowed ) {
274                         /* NOTE: do not copy the structure until required */
275                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
276                                 db = *op->o_bd;
277                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
278                                 op->o_bd = &db;
279                         }
280
281                         op->o_bd->bd_info = (BackendInfo *)on;
282                         rc = on->on_bi.bi_access_allowed( op, e,
283                                 desc, val, access, state, maskp );
284                         if ( rc != SLAP_CB_CONTINUE ) break;
285                 }
286         }
287
288         if ( rc == SLAP_CB_CONTINUE ) {
289                 BI_access_allowed       *bi_access_allowed;
290
291                 /* if the database structure was changed, o_bd points to a
292                  * copy of the structure; put the original bd_info in place */
293                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
294                         op->o_bd->bd_info = oi->oi_orig;
295                 }
296
297                 if ( oi->oi_orig->bi_access_allowed ) {
298                         bi_access_allowed = oi->oi_orig->bi_access_allowed;
299                 } else {
300                         bi_access_allowed = slap_access_allowed;
301                 }
302
303                 rc = bi_access_allowed( op, e,
304                         desc, val, access, state, maskp );
305         }
306         /* should not fall thru this far without anything happening... */
307         if ( rc == SLAP_CB_CONTINUE ) {
308                 /* access not allowed */
309                 rc = 0;
310         }
311
312         op->o_bd = be;
313         op->o_bd->bd_info = bi;
314
315         return rc;
316 }
317
318 static int
319 over_acl_group(
320         Operation               *op,
321         Entry                   *e,
322         struct berval           *gr_ndn,
323         struct berval           *op_ndn,
324         ObjectClass             *group_oc,
325         AttributeDescription    *group_at )
326 {
327         slap_overinfo *oi;
328         slap_overinst *on;
329         BackendInfo *bi = op->o_bd->bd_info;
330         BackendDB *be = op->o_bd, db;
331         int rc = SLAP_CB_CONTINUE;
332
333         /* FIXME: used to happen for instance during abandon
334          * when global overlays are used... */
335         assert( op->o_bd != NULL );
336
337         oi = op->o_bd->bd_info->bi_private;
338         on = oi->oi_list;
339
340         for ( ; on; on = on->on_next ) {
341                 if ( on->on_bi.bi_acl_group ) {
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_acl_group( op, e,
351                                 gr_ndn, op_ndn, group_oc, group_at );
352                         if ( rc != SLAP_CB_CONTINUE ) break;
353                 }
354         }
355
356         if ( rc == SLAP_CB_CONTINUE ) {
357                 BI_acl_group            *bi_acl_group;
358
359                 /* if the database structure was changed, o_bd points to a
360                  * copy of the structure; put the original bd_info in place */
361                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
362                         op->o_bd->bd_info = oi->oi_orig;
363                 }
364
365                 if ( oi->oi_orig->bi_acl_group ) {
366                         bi_acl_group = oi->oi_orig->bi_acl_group;
367                 } else {
368                         bi_acl_group = backend_group;
369                 }
370
371                 rc = bi_acl_group( op, e,
372                         gr_ndn, op_ndn, group_oc, group_at );
373         }
374         /* should not fall thru this far without anything happening... */
375         if ( rc == SLAP_CB_CONTINUE ) {
376                 /* access not allowed */
377                 rc = 0;
378         }
379
380         op->o_bd = be;
381         op->o_bd->bd_info = bi;
382
383         return rc;
384 }
385
386 static int
387 over_acl_attribute(
388         Operation               *op,
389         Entry                   *target,
390         struct berval           *entry_ndn,
391         AttributeDescription    *entry_at,
392         BerVarray               *vals,
393         slap_access_t           access )
394 {
395         slap_overinfo *oi;
396         slap_overinst *on;
397         BackendInfo *bi = op->o_bd->bd_info;
398         BackendDB *be = op->o_bd, db;
399         int rc = SLAP_CB_CONTINUE;
400
401         /* FIXME: used to happen for instance during abandon
402          * when global overlays are used... */
403         assert( op->o_bd != NULL );
404
405         oi = op->o_bd->bd_info->bi_private;
406         on = oi->oi_list;
407
408         for ( ; on; on = on->on_next ) {
409                 if ( on->on_bi.bi_acl_attribute ) {
410                         /* NOTE: do not copy the structure until required */
411                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
412                                 db = *op->o_bd;
413                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
414                                 op->o_bd = &db;
415                         }
416
417                         op->o_bd->bd_info = (BackendInfo *)on;
418                         rc = on->on_bi.bi_acl_attribute( op, target,
419                                 entry_ndn, entry_at, vals, access );
420                         if ( rc != SLAP_CB_CONTINUE ) break;
421                 }
422         }
423
424         if ( rc == SLAP_CB_CONTINUE ) {
425                 BI_acl_attribute                *bi_acl_attribute;
426
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_acl_attribute ) {
434                         bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
435                 } else {
436                         bi_acl_attribute = backend_attribute;
437                 }
438
439                 rc = bi_acl_attribute( op, target,
440                         entry_ndn, entry_at, vals, access );
441         }
442         /* should not fall thru this far without anything happening... */
443         if ( rc == SLAP_CB_CONTINUE ) {
444                 /* access not allowed */
445                 rc = 0;
446         }
447
448         op->o_bd = be;
449         op->o_bd->bd_info = bi;
450
451         return rc;
452 }
453 #endif /* SLAP_OVERLAY_ACCESS */
454
455 /*
456  * default return code in case of missing backend function
457  * and overlay stack returning SLAP_CB_CONTINUE
458  */
459 static int op_rc[ op_last ] = {
460         LDAP_UNWILLING_TO_PERFORM,      /* bind */
461         LDAP_UNWILLING_TO_PERFORM,      /* unbind */
462         LDAP_UNWILLING_TO_PERFORM,      /* search */
463         SLAP_CB_CONTINUE,               /* compare; pass to frontend */
464         LDAP_UNWILLING_TO_PERFORM,      /* modify */
465         LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
466         LDAP_UNWILLING_TO_PERFORM,      /* add */
467         LDAP_UNWILLING_TO_PERFORM,      /* delete */
468         LDAP_UNWILLING_TO_PERFORM,      /* abandon */
469         LDAP_UNWILLING_TO_PERFORM,      /* cancel */
470         LDAP_UNWILLING_TO_PERFORM,      /* extended */
471         LDAP_SUCCESS,                   /* aux_operational */
472         LDAP_SUCCESS,                   /* aux_chk_referrals */
473         SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
474 };
475
476 int overlay_op_walk(
477         Operation *op,
478         SlapReply *rs,
479         slap_operation_t which,
480         slap_overinfo *oi,
481         slap_overinst *on
482 )
483 {
484         BI_op_bind **func;
485         int rc = SLAP_CB_CONTINUE;
486
487         for (; on; on=on->on_next ) {
488                 func = &on->on_bi.bi_op_bind;
489                 if ( func[which] ) {
490                         op->o_bd->bd_info = (BackendInfo *)on;
491                         rc = func[which]( op, rs );
492                         if ( rc != SLAP_CB_CONTINUE ) break;
493                 }
494         }
495
496         func = &oi->oi_orig->bi_op_bind;
497         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
498                 op->o_bd->bd_info = oi->oi_orig;
499                 rc = func[which]( op, rs );
500         }
501         /* should not fall thru this far without anything happening... */
502         if ( rc == SLAP_CB_CONTINUE ) {
503                 rc = op_rc[ which ];
504         }
505
506         /* The underlying backend didn't handle the request, make sure
507          * overlay cleanup is processed.
508          */
509         if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
510                 slap_callback *sc_next;
511                 for ( ; op->o_callback && op->o_callback->sc_response !=
512                         over_back_response; op->o_callback = sc_next ) {
513                         sc_next = op->o_callback->sc_next;
514                         if ( op->o_callback->sc_cleanup ) {
515                                 op->o_callback->sc_cleanup( op, rs );
516                         }
517                 }
518         }
519         return rc;
520 }
521
522 static int
523 over_op_func(
524         Operation *op,
525         SlapReply *rs,
526         slap_operation_t which
527 )
528 {
529         slap_overinfo *oi;
530         slap_overinst *on;
531         BackendDB *be = op->o_bd, db;
532         slap_callback cb = {NULL, over_back_response, NULL, NULL};
533         int rc = SLAP_CB_CONTINUE;
534
535         /* FIXME: used to happen for instance during abandon
536          * when global overlays are used... */
537         assert( op->o_bd != NULL );
538
539         oi = op->o_bd->bd_info->bi_private;
540         on = oi->oi_list;
541
542         if ( !SLAP_ISOVERLAY( op->o_bd )) {
543                 db = *op->o_bd;
544                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
545                 op->o_bd = &db;
546         }
547         cb.sc_next = op->o_callback;
548         cb.sc_private = oi;
549         op->o_callback = &cb;
550
551         rc = overlay_op_walk( op, rs, which, oi, on );
552
553         op->o_bd = be;
554         op->o_callback = cb.sc_next;
555         return rc;
556 }
557
558 static int
559 over_op_bind( Operation *op, SlapReply *rs )
560 {
561         return over_op_func( op, rs, op_bind );
562 }
563
564 static int
565 over_op_unbind( Operation *op, SlapReply *rs )
566 {
567         return over_op_func( op, rs, op_unbind );
568 }
569
570 static int
571 over_op_search( Operation *op, SlapReply *rs )
572 {
573         return over_op_func( op, rs, op_search );
574 }
575
576 static int
577 over_op_compare( Operation *op, SlapReply *rs )
578 {
579         return over_op_func( op, rs, op_compare );
580 }
581
582 static int
583 over_op_modify( Operation *op, SlapReply *rs )
584 {
585         return over_op_func( op, rs, op_modify );
586 }
587
588 static int
589 over_op_modrdn( Operation *op, SlapReply *rs )
590 {
591         return over_op_func( op, rs, op_modrdn );
592 }
593
594 static int
595 over_op_add( Operation *op, SlapReply *rs )
596 {
597         return over_op_func( op, rs, op_add );
598 }
599
600 static int
601 over_op_delete( Operation *op, SlapReply *rs )
602 {
603         return over_op_func( op, rs, op_delete );
604 }
605
606 static int
607 over_op_abandon( Operation *op, SlapReply *rs )
608 {
609         return over_op_func( op, rs, op_abandon );
610 }
611
612 static int
613 over_op_cancel( Operation *op, SlapReply *rs )
614 {
615         return over_op_func( op, rs, op_cancel );
616 }
617
618 static int
619 over_op_extended( Operation *op, SlapReply *rs )
620 {
621         return over_op_func( op, rs, op_extended );
622 }
623
624 static int
625 over_aux_operational( Operation *op, SlapReply *rs )
626 {
627         return over_op_func( op, rs, op_aux_operational );
628 }
629
630 static int
631 over_aux_chk_referrals( Operation *op, SlapReply *rs )
632 {
633         return over_op_func( op, rs, op_aux_chk_referrals );
634 }
635
636 static int
637 over_aux_chk_controls( Operation *op, SlapReply *rs )
638 {
639         return over_op_func( op, rs, op_aux_chk_controls );
640 }
641
642 enum conn_which {
643         conn_init = 0,
644         conn_destroy,
645         conn_last
646 };
647
648 static int
649 over_connection_func(
650         BackendDB       *bd,
651         Connection      *conn,
652         enum conn_which which
653 )
654 {
655         slap_overinfo           *oi;
656         slap_overinst           *on;
657         BackendDB               db;
658         int                     rc = SLAP_CB_CONTINUE;
659         BI_connection_init      **func;
660
661         /* FIXME: used to happen for instance during abandon
662          * when global overlays are used... */
663         assert( bd != NULL );
664
665         oi = bd->bd_info->bi_private;
666         on = oi->oi_list;
667
668         if ( !SLAP_ISOVERLAY( bd ) ) {
669                 db = *bd;
670                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
671                 bd = &db;
672         }
673
674         for ( ; on; on = on->on_next ) {
675                 func = &on->on_bi.bi_connection_init;
676                 if ( func[ which ] ) {
677                         bd->bd_info = (BackendInfo *)on;
678                         rc = func[ which ]( bd, conn );
679                         if ( rc != SLAP_CB_CONTINUE ) break;
680                 }
681         }
682
683         func = &oi->oi_orig->bi_connection_init;
684         if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
685                 bd->bd_info = oi->oi_orig;
686                 rc = func[ which ]( bd, conn );
687         }
688         /* should not fall thru this far without anything happening... */
689         if ( rc == SLAP_CB_CONTINUE ) {
690                 rc = LDAP_UNWILLING_TO_PERFORM;
691         }
692
693         return rc;
694 }
695
696 static int
697 over_connection_init(
698         BackendDB       *bd,
699         Connection      *conn
700 )
701 {
702         return over_connection_func( bd, conn, conn_init );
703 }
704
705 static int
706 over_connection_destroy(
707         BackendDB       *bd,
708         Connection      *conn
709 )
710 {
711         return over_connection_func( bd, conn, conn_destroy );
712 }
713
714 int
715 overlay_register(
716         slap_overinst *on
717 )
718 {
719         on->on_next = overlays;
720         overlays = on;
721         return 0;
722 }
723
724 /*
725  * iterator on registered overlays; overlay_next( NULL ) returns the first
726  * overlay; * subsequent calls with the previously returned value allow to 
727  * iterate * over the entire list; returns NULL when no more overlays are 
728  * registered.
729  */
730
731 slap_overinst *
732 overlay_next(
733         slap_overinst *on
734 )
735 {
736         if ( on == NULL ) {
737                 return overlays;
738         }
739
740         return on->on_next;
741 }
742
743 /*
744  * returns a specific registered overlay based on the type; NULL if not
745  * registered.
746  */
747
748 slap_overinst *
749 overlay_find( const char *over_type )
750 {
751         slap_overinst *on = overlays;
752
753         assert( over_type != NULL );
754
755         for ( ; on; on = on->on_next ) {
756                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
757                         break;
758                 }
759         }
760
761         return on;
762 }
763
764 static const char overtype[] = "over";
765
766 /*
767  * returns TRUE (1) if the database is actually an overlay instance;
768  * FALSE (0) otherwise.
769  */
770
771 int
772 overlay_is_over( BackendDB *be )
773 {
774         return be->bd_info->bi_type == overtype;
775 }
776
777 /*
778  * returns TRUE (1) if the given database is actually an overlay
779  * instance and, somewhere in the list, contains the requested overlay;
780  * FALSE (0) otherwise.
781  */
782
783 int
784 overlay_is_inst( BackendDB *be, const char *over_type )
785 {
786         slap_overinst   *on;
787
788         assert( be != NULL );
789
790         if ( !overlay_is_over( be ) ) {
791                 return 0;
792         }
793         
794         on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
795         for ( ; on; on = on->on_next ) {
796                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
797                         return 1;
798                 }
799         }
800
801         return 0;
802 }
803
804 int
805 overlay_register_control( BackendDB *be, const char *oid )
806 {
807         int             gotit = 0;
808         int             cid;
809
810         if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
811                 return -1;
812         }
813
814         if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
815                 BackendDB *bd;
816                 
817                 /* add to all backends... */
818                 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
819                         if ( be == bd ) {
820                                 gotit = 1;
821                         }
822
823                         bd->be_ctrls[ cid ] = 1;
824                         bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
825                 }
826
827         }
828         
829         if ( !gotit ) {
830                 be->be_ctrls[ cid ] = 1;
831                 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
832         }
833
834         return 0;
835 }
836
837 void
838 overlay_destroy_one( BackendDB *be, slap_overinst *on )
839 {
840         slap_overinfo *oi = on->on_info;
841         slap_overinst **oidx;
842
843         for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
844                 if ( *oidx == on ) {
845                         *oidx = on->on_next;
846                         if ( on->on_bi.bi_db_destroy ) {
847                                 BackendInfo *bi_orig = be->bd_info;
848                                 be->bd_info = (BackendInfo *)on;
849                                 on->on_bi.bi_db_destroy( be );
850                                 be->bd_info = bi_orig;
851                         }
852                         free( on );
853                         break;
854                 }
855         }
856 }
857
858 /* add an overlay to a particular backend. */
859 int
860 overlay_config( BackendDB *be, const char *ov )
861 {
862         slap_overinst *on = NULL, *on2 = NULL;
863         slap_overinfo *oi = NULL;
864         BackendInfo *bi = NULL;
865
866         on = overlay_find( ov );
867         if ( !on ) {
868                 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
869                 return 1;
870         }
871
872         /* If this is the first overlay on this backend, set up the
873          * overlay info structure
874          */
875         if ( !overlay_is_over( be ) ) {
876                 oi = ch_malloc( sizeof( slap_overinfo ) );
877                 oi->oi_orig = be->bd_info;
878                 oi->oi_bi = *be->bd_info;
879                 oi->oi_origdb = be;
880
881                 /* NOTE: the first time a global overlay is configured,
882                  * frontendDB gets this flag; it is used later by overlays
883                  * to determine if they're stacked on top of the frontendDB */
884                 if ( oi->oi_orig == frontendDB->bd_info ) {
885                         SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
886                 }
887
888                 /* Save a pointer to ourself in bi_private.
889                  */
890                 oi->oi_bi.bi_private = oi;
891                 oi->oi_list = NULL;
892                 bi = (BackendInfo *)oi;
893
894                 bi->bi_type = (char *)overtype;
895
896                 bi->bi_db_config = over_db_config;
897                 bi->bi_db_open = over_db_open;
898                 bi->bi_db_close = over_db_close;
899                 bi->bi_db_destroy = over_db_destroy;
900
901                 bi->bi_op_bind = over_op_bind;
902                 bi->bi_op_unbind = over_op_unbind;
903                 bi->bi_op_search = over_op_search;
904                 bi->bi_op_compare = over_op_compare;
905                 bi->bi_op_modify = over_op_modify;
906                 bi->bi_op_modrdn = over_op_modrdn;
907                 bi->bi_op_add = over_op_add;
908                 bi->bi_op_delete = over_op_delete;
909                 bi->bi_op_abandon = over_op_abandon;
910                 bi->bi_op_cancel = over_op_cancel;
911
912                 bi->bi_extended = over_op_extended;
913
914                 /*
915                  * this is fine because it has the same
916                  * args of the operations; we need to rework
917                  * all the hooks to share the same args
918                  * of the operations...
919                  */
920                 bi->bi_operational = over_aux_operational;
921                 bi->bi_chk_referrals = over_aux_chk_referrals;
922                 bi->bi_chk_controls = over_aux_chk_controls;
923
924 #ifdef SLAP_OVERLAY_ACCESS
925                 /* these have specific arglists */
926                 bi->bi_access_allowed = over_access_allowed;
927                 bi->bi_acl_group = over_acl_group;
928                 bi->bi_acl_attribute = over_acl_attribute;
929 #endif /* SLAP_OVERLAY_ACCESS */
930                 
931                 bi->bi_connection_init = over_connection_init;
932                 bi->bi_connection_destroy = over_connection_destroy;
933
934                 be->bd_info = bi;
935
936         } else {
937                 if ( overlay_is_inst( be, ov ) ) {
938                         Debug( LDAP_DEBUG_ANY, "overlay_config(): "
939                                         "warning, overlay \"%s\" "
940                                         "already in list\n", ov, 0, 0 );
941                 }
942
943                 oi = be->bd_info->bi_private;
944         }
945
946         /* Insert new overlay on head of list. Overlays are executed
947          * in reverse of config order...
948          */
949         on2 = ch_calloc( 1, sizeof(slap_overinst) );
950         *on2 = *on;
951         on2->on_info = oi;
952         on2->on_next = oi->oi_list;
953         oi->oi_list = on2;
954
955         /* Any initialization needed? */
956         if ( on->on_bi.bi_db_init ) {
957                 int rc;
958                 be->bd_info = (BackendInfo *)on2;
959                 rc = on2->on_bi.bi_db_init( be );
960                 be->bd_info = (BackendInfo *)oi;
961                 if ( rc ) return rc;
962         }
963
964         return 0;
965 }
966