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