1 /* backover.c - backend overlay routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 /* Functions to overlay other modules over a backend. */
23 #include <ac/string.h>
24 #include <ac/socket.h>
29 static slap_overinst *overlays;
31 enum db_which { db_open = 0, db_close, db_destroy };
39 slap_overinfo *oi = be->bd_info->bi_private;
40 slap_overinst *on = oi->oi_list;
41 BackendInfo *bi_orig = be->bd_info;
45 func = &oi->oi_orig->bi_db_open;
47 be->bd_info = oi->oi_orig;
48 rc = func[which]( be );
51 for (; on && rc == 0; on=on->on_next) {
52 be->bd_info = &on->on_bi;
53 func = &on->on_bi.bi_db_open;
55 rc = func[which]( be );
58 be->bd_info = bi_orig;
71 slap_overinfo *oi = be->bd_info->bi_private;
72 slap_overinst *on = oi->oi_list;
73 BackendInfo *bi_orig = be->bd_info;
76 if ( oi->oi_orig->bi_db_config ) {
77 be->bd_info = oi->oi_orig;
78 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
80 be->bd_info = (BackendInfo *)oi;
81 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
84 for (; on; on=on->on_next) {
85 if (on->on_bi.bi_db_config) {
86 be->bd_info = &on->on_bi;
87 rc = on->on_bi.bi_db_config( be, fname, lineno,
89 if ( rc != SLAP_CONF_UNKNOWN ) break;
92 be->bd_info = bi_orig;
101 return over_db_func( be, db_open );
109 return over_db_func( be, db_close );
117 slap_overinfo *oi = be->bd_info->bi_private;
118 slap_overinst *on = oi->oi_list, *next;
121 rc = over_db_func( be, db_destroy );
123 for (next = on->on_next; on; on=next) {
132 over_back_response ( Operation *op, SlapReply *rs )
134 slap_overinfo *oi = op->o_callback->sc_private;
135 slap_overinst *on = oi->oi_list;
136 int rc = SLAP_CB_CONTINUE;
137 BackendDB *be = op->o_bd, db = *op->o_bd;
140 for (; on; on=on->on_next ) {
141 if ( on->on_response ) {
142 db.bd_info = (BackendInfo *)on;
143 rc = on->on_response( op, rs );
144 if ( rc != SLAP_CB_CONTINUE ) break;
163 op_aux_chk_referrals,
168 * default return code in case of missing backend function
169 * and overlay stack returning SLAP_CB_CONTINUE
171 static int op_rc[] = {
172 LDAP_UNWILLING_TO_PERFORM, /* bind */
173 LDAP_UNWILLING_TO_PERFORM, /* unbind */
174 LDAP_UNWILLING_TO_PERFORM, /* search */
175 LDAP_UNWILLING_TO_PERFORM, /* compare */
176 LDAP_UNWILLING_TO_PERFORM, /* modify */
177 LDAP_UNWILLING_TO_PERFORM, /* modrdn */
178 LDAP_UNWILLING_TO_PERFORM, /* add */
179 LDAP_UNWILLING_TO_PERFORM, /* delete */
180 LDAP_UNWILLING_TO_PERFORM, /* abandon */
181 LDAP_UNWILLING_TO_PERFORM, /* cancel */
182 LDAP_UNWILLING_TO_PERFORM, /* extended */
183 LDAP_SUCCESS /* aux_chk_referrals */
193 slap_overinfo *oi = op->o_bd->bd_info->bi_private;
194 slap_overinst *on = oi->oi_list;
196 BackendDB *be = op->o_bd, db = *op->o_bd;
197 slap_callback cb = {NULL, over_back_response, NULL, NULL};
198 int rc = SLAP_CB_CONTINUE;
201 cb.sc_next = op->o_callback;
203 op->o_callback = &cb;
205 for (; on; on=on->on_next ) {
206 func = &on->on_bi.bi_op_bind;
208 db.bd_info = (BackendInfo *)on;
209 rc = func[which]( op, rs );
210 if ( rc != SLAP_CB_CONTINUE ) break;
214 func = &oi->oi_orig->bi_op_bind;
215 if ( func[which] && rc == SLAP_CB_CONTINUE ) {
216 db.bd_info = oi->oi_orig;
217 rc = func[which]( op, rs );
219 /* should not fall thru this far without anything happening... */
220 if ( rc == SLAP_CB_CONTINUE ) {
224 op->o_callback = cb.sc_next;
229 over_op_bind( Operation *op, SlapReply *rs )
231 return over_op_func( op, rs, op_bind );
235 over_op_unbind( Operation *op, SlapReply *rs )
237 return over_op_func( op, rs, op_unbind );
241 over_op_search( Operation *op, SlapReply *rs )
243 return over_op_func( op, rs, op_search );
247 over_op_compare( Operation *op, SlapReply *rs )
249 return over_op_func( op, rs, op_compare );
253 over_op_modify( Operation *op, SlapReply *rs )
255 return over_op_func( op, rs, op_modify );
259 over_op_modrdn( Operation *op, SlapReply *rs )
261 return over_op_func( op, rs, op_modrdn );
265 over_op_add( Operation *op, SlapReply *rs )
267 return over_op_func( op, rs, op_add );
271 over_op_delete( Operation *op, SlapReply *rs )
273 return over_op_func( op, rs, op_delete );
277 over_op_abandon( Operation *op, SlapReply *rs )
279 return over_op_func( op, rs, op_abandon );
283 over_op_cancel( Operation *op, SlapReply *rs )
285 return over_op_func( op, rs, op_cancel );
289 over_op_extended( Operation *op, SlapReply *rs )
291 return over_op_func( op, rs, op_extended );
295 over_chk_referrals( Operation *op, SlapReply *rs )
297 return over_op_func( op, rs, op_aux_chk_referrals );
305 on->on_next = overlays;
322 static const char overtype[] = "over";
324 /* add an overlay to a particular backend. */
326 overlay_config( BackendDB *be, const char *ov )
328 slap_overinst *on = NULL, *on2 = NULL, *prev = NULL;
329 slap_overinfo *oi = NULL;
330 BackendInfo *bi = NULL;
332 for ( on = overlays; on; on=on->on_next ) {
333 if (!strcmp( ov, on->on_bi.bi_type ) )
337 Debug( LDAP_DEBUG_ANY, "overlay %s not found\n", ov, 0, 0 );
341 /* If this is the first overlay on this backend, set up the
342 * overlay info structure
344 if ( be->bd_info->bi_type != overtype ) {
345 oi = ch_malloc( sizeof(slap_overinfo) );
346 oi->oi_orig = be->bd_info;
347 oi->oi_bi = *be->bd_info;
349 /* Save a pointer to ourself in bi_private.
350 * This allows us to keep working in conjunction
353 oi->oi_bi.bi_private = oi;
355 bi = (BackendInfo *)oi;
357 bi->bi_type = (char *)overtype;
359 bi->bi_db_config = over_db_config;
360 bi->bi_db_open = over_db_open;
361 bi->bi_db_close = over_db_close;
362 bi->bi_db_destroy = over_db_destroy;
364 bi->bi_op_bind = over_op_bind;
365 bi->bi_op_unbind = over_op_unbind;
366 bi->bi_op_search = over_op_search;
367 bi->bi_op_compare = over_op_compare;
368 bi->bi_op_modify = over_op_modify;
369 bi->bi_op_modrdn = over_op_modrdn;
370 bi->bi_op_add = over_op_add;
371 bi->bi_op_delete = over_op_delete;
372 bi->bi_op_abandon = over_op_abandon;
373 bi->bi_op_cancel = over_op_cancel;
375 bi->bi_extended = over_op_extended;
378 * this is fine because it has the same
379 * args of the operations; we need to rework
380 * all the hooks to share the same args
381 * of the operations...
383 bi->bi_chk_referrals = over_chk_referrals;
388 oi = be->bd_info->bi_private;
392 /* Walk to the end of the list of overlays, add the new
395 for ( prev=NULL, on2 = oi->oi_list; on2; prev=on2, on2=on2->on_next );
396 on2 = ch_calloc( 1, sizeof(slap_overinst) );
406 /* Insert new overlay on head of list. Overlays are executed
407 * in reverse of config order...
409 on2 = ch_calloc( 1, sizeof(slap_overinst) );
412 on2->on_next = oi->oi_list;
416 /* Any initialization needed? */
417 if ( on->on_bi.bi_db_init ) {
418 be->bd_info = (BackendInfo *)on2;
419 on2->on_bi.bi_db_init( be );
420 be->bd_info = (BackendInfo *)oi;