]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
5f3f1e5ec863c3acfe99795577b3dcbe49852adc
[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-2004 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
29 static slap_overinst *overlays = NULL;
30
31 enum db_which { db_open = 0, db_close, db_destroy };
32
33 static int
34 over_db_func(
35         BackendDB *be,
36         enum db_which which
37 )
38 {
39         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
40         slap_overinst *on = oi->oi_list;
41         BI_db_open **func;
42         int rc = 0;
43
44         func = &oi->oi_orig->bi_db_open;
45         if ( func[which] ) {
46                 be->bd_info = oi->oi_orig;
47                 rc = func[which]( be );
48         }
49
50         for (; on && rc == 0; on=on->on_next) {
51                 be->bd_info = &on->on_bi;
52                 func = &on->on_bi.bi_db_open;
53                 if (func[which]) {
54                         rc = func[which]( be );
55                 }
56         }
57         be->bd_info = (BackendInfo *)oi;
58         return rc;
59 }
60
61 static int
62 over_db_config(
63         BackendDB *be,
64         const char *fname,
65         int lineno,
66         int argc,
67         char **argv
68 )
69 {
70         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
71         slap_overinst *on = oi->oi_list;
72         int rc = 0;
73
74         if ( oi->oi_orig->bi_db_config ) {
75                 be->bd_info = oi->oi_orig;
76                 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
77                         argc, argv );
78                 be->bd_info = (BackendInfo *)oi;
79                 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
80         }
81
82         for (; on; on=on->on_next) {
83                 if (on->on_bi.bi_db_config) {
84                         be->bd_info = &on->on_bi;
85                         rc = on->on_bi.bi_db_config( be, fname, lineno,
86                                 argc, argv );
87                         if ( rc != SLAP_CONF_UNKNOWN ) break;
88                 }
89         }
90         be->bd_info = (BackendInfo *)oi;
91         return rc;
92 }
93
94 static int
95 over_db_open(
96         BackendDB *be
97 )
98 {
99         return over_db_func( be, db_open );
100 }
101
102 static int
103 over_db_close(
104         BackendDB *be
105 )
106 {
107         return over_db_func( be, db_close );
108 }
109
110 static int
111 over_db_destroy(
112         BackendDB *be
113 )
114 {
115         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
116         slap_overinst *on = oi->oi_list, *next;
117         int rc;
118
119         rc = over_db_func( be, db_destroy );
120
121         for (next = on->on_next; on; on=next) {
122                 next = on->on_next;
123                 free( on );
124         }
125         free( oi );
126         return rc;
127 }
128
129 static int
130 over_back_response ( Operation *op, SlapReply *rs )
131 {
132         slap_overinfo *oi = op->o_callback->sc_private;
133         slap_overinst *on = oi->oi_list;
134         int rc = SLAP_CB_CONTINUE;
135         BackendDB *be = op->o_bd, db = *op->o_bd;
136
137         op->o_bd = &db;
138         for (; on; on=on->on_next ) {
139                 if ( on->on_response ) {
140                         db.bd_info = (BackendInfo *)on;
141                         rc = on->on_response( op, rs );
142                         if ( rc != SLAP_CB_CONTINUE ) break;
143                 }
144         }
145         op->o_bd = be;
146         return rc;
147 }
148
149 enum op_which {
150         op_bind = 0,
151         op_unbind,
152         op_search,
153         op_compare,
154         op_modify,
155         op_modrdn,
156         op_add,
157         op_delete,
158         op_abandon,
159         op_cancel,
160         op_extended,
161         op_aux_chk_referrals,
162         op_last
163 };
164
165 /*
166  * default return code in case of missing backend function
167  * and overlay stack returning SLAP_CB_CONTINUE
168  */
169 static int op_rc[] = {
170         LDAP_UNWILLING_TO_PERFORM,      /* bind */
171         LDAP_UNWILLING_TO_PERFORM,      /* unbind */
172         LDAP_UNWILLING_TO_PERFORM,      /* search */
173         LDAP_UNWILLING_TO_PERFORM,      /* compare */
174         LDAP_UNWILLING_TO_PERFORM,      /* modify */
175         LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
176         LDAP_UNWILLING_TO_PERFORM,      /* add */
177         LDAP_UNWILLING_TO_PERFORM,      /* delete */
178         LDAP_UNWILLING_TO_PERFORM,      /* abandon */
179         LDAP_UNWILLING_TO_PERFORM,      /* cancel */
180         LDAP_UNWILLING_TO_PERFORM,      /* extended */
181         LDAP_SUCCESS                    /* aux_chk_referrals */
182 };
183
184 static int
185 over_op_func(
186         Operation *op,
187         SlapReply *rs,
188         enum op_which which
189 )
190 {
191         slap_overinfo *oi = (slap_overinfo *) op->o_bd->bd_info;
192         slap_overinst *on = oi->oi_list;
193         BI_op_bind **func;
194         BackendDB *be = op->o_bd, db = *op->o_bd;
195         slap_callback cb = {NULL, over_back_response, NULL, NULL};
196         int rc = SLAP_CB_CONTINUE;
197
198         op->o_bd = &db;
199         cb.sc_next = op->o_callback;
200         cb.sc_private = oi;
201         op->o_callback = &cb;
202
203         for (; on; on=on->on_next ) {
204                 func = &on->on_bi.bi_op_bind;
205                 if ( func[which] ) {
206                         db.bd_info = (BackendInfo *)on;
207                         rc = func[which]( op, rs );
208                         if ( rc != SLAP_CB_CONTINUE ) break;
209                 }
210         }
211
212         op->o_bd = be;
213         func = &oi->oi_orig->bi_op_bind;
214         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
215                 rc = func[which]( op, rs );
216         }
217         /* should not fall thru this far without anything happening... */
218         if ( rc == SLAP_CB_CONTINUE ) {
219                 rc = op_rc[ which ];
220         }
221         op->o_callback = cb.sc_next;
222         return rc;
223 }
224
225 static int
226 over_op_bind( Operation *op, SlapReply *rs )
227 {
228         return over_op_func( op, rs, op_bind );
229 }
230
231 static int
232 over_op_unbind( Operation *op, SlapReply *rs )
233 {
234         return over_op_func( op, rs, op_unbind );
235 }
236
237 static int
238 over_op_search( Operation *op, SlapReply *rs )
239 {
240         return over_op_func( op, rs, op_search );
241 }
242
243 static int
244 over_op_compare( Operation *op, SlapReply *rs )
245 {
246         return over_op_func( op, rs, op_compare );
247 }
248
249 static int
250 over_op_modify( Operation *op, SlapReply *rs )
251 {
252         return over_op_func( op, rs, op_modify );
253 }
254
255 static int
256 over_op_modrdn( Operation *op, SlapReply *rs )
257 {
258         return over_op_func( op, rs, op_modrdn );
259 }
260
261 static int
262 over_op_add( Operation *op, SlapReply *rs )
263 {
264         return over_op_func( op, rs, op_add );
265 }
266
267 static int
268 over_op_delete( Operation *op, SlapReply *rs )
269 {
270         return over_op_func( op, rs, op_delete );
271 }
272
273 static int
274 over_op_abandon( Operation *op, SlapReply *rs )
275 {
276         return over_op_func( op, rs, op_abandon );
277 }
278
279 static int
280 over_op_cancel( Operation *op, SlapReply *rs )
281 {
282         return over_op_func( op, rs, op_cancel );
283 }
284
285 static int
286 over_op_extended( Operation *op, SlapReply *rs )
287 {
288         return over_op_func( op, rs, op_extended );
289 }
290
291 static int
292 over_chk_referrals( Operation *op, SlapReply *rs )
293 {
294         return over_op_func( op, rs, op_aux_chk_referrals );
295 }
296
297 int
298 overlay_register(
299         slap_overinst *on
300 )
301 {
302         on->on_next = overlays;
303         overlays = on;
304         return 0;
305 }
306
307 slap_overinst *
308 overlay_next(
309         slap_overinst *on
310 )
311 {
312         if ( on == NULL ) {
313                 return overlays;
314         }
315
316         return on->on_next;
317 }
318
319 static const char overtype[] = "over";
320
321 /* add an overlay to a particular backend. */
322 int
323 overlay_config( BackendDB *be, const char *ov )
324 {
325         slap_overinst *on = NULL, *on2 = NULL, *prev = NULL;
326         slap_overinfo *oi = NULL;
327         BackendInfo *bi = NULL;
328
329         for ( on = overlays; on; on=on->on_next ) {
330                 if (!strcmp( ov, on->on_bi.bi_type ) )
331                         break;
332         }
333         if (!on) {
334                 Debug( LDAP_DEBUG_ANY, "overlay %s not found\n", ov, 0, 0 );
335                 return 1;
336         }
337
338         /* If this is the first overlay on this backend, set up the
339          * overlay info structure
340          */
341         if ( be->bd_info->bi_type != overtype ) {
342                 oi = ch_malloc( sizeof(slap_overinfo) );
343                 oi->oi_orig = be->bd_info;
344                 oi->oi_bi = *be->bd_info;
345                 oi->oi_list = NULL;
346                 bi = (BackendInfo *)oi;
347
348                 bi->bi_type = (char *)overtype;
349
350                 bi->bi_db_config = over_db_config;
351                 bi->bi_db_open = over_db_open;
352                 bi->bi_db_close = over_db_close;
353                 bi->bi_db_destroy = over_db_destroy;
354
355                 bi->bi_op_bind = over_op_bind;
356                 bi->bi_op_unbind = over_op_unbind;
357                 bi->bi_op_search = over_op_search;
358                 bi->bi_op_compare = over_op_compare;
359                 bi->bi_op_modify = over_op_modify;
360                 bi->bi_op_modrdn = over_op_modrdn;
361                 bi->bi_op_add = over_op_add;
362                 bi->bi_op_delete = over_op_delete;
363                 bi->bi_op_abandon = over_op_abandon;
364                 bi->bi_op_cancel = over_op_cancel;
365
366                 bi->bi_extended = over_op_extended;
367
368                 /*
369                  * this is fine because it has the same
370                  * args of the operations; we need to rework
371                  * all the hooks to share the same args
372                  * of the operations...
373                  */
374                 bi->bi_chk_referrals = over_chk_referrals;
375
376                 be->bd_info = bi;
377
378         } else {
379                 oi = (slap_overinfo *) be->bd_info;
380         }
381
382 #if 0
383         /* Walk to the end of the list of overlays, add the new
384          * one onto the end
385          */
386         for ( prev=NULL, on2 = oi->oi_list; on2; prev=on2, on2=on2->on_next );
387         on2 = ch_calloc( 1, sizeof(slap_overinst) );
388         if ( !prev ) {
389                 oi->oi_list = on2;
390         } else {
391                 prev->on_next = on2;
392         }
393         *on2 = *on;
394         on2->on_next = NULL;
395         on2->on_info = oi;
396 #else
397         /* Insert new overlay on head of list. Overlays are executed
398          * in reverse of config order...
399          */
400         on2 = ch_calloc( 1, sizeof(slap_overinst) );
401         *on2 = *on;
402         on2->on_info = oi;
403         on2->on_next = oi->oi_list;
404         oi->oi_list = on2;
405 #endif
406
407         /* Any initialization needed? */
408         if ( on->on_bi.bi_db_init ) {
409                 be->bd_info = (BackendInfo *)on2;
410                 on2->on_bi.bi_db_init( be );
411                 be->bd_info = (BackendInfo *)oi;
412         }
413
414         return 0;
415 }
416