]> git.sur5r.net Git - openldap/blob - servers/slapd/back-relay/op.c
actually, teh backend could also be selected on a per-operation basis, if "relay...
[openldap] / servers / slapd / back-relay / op.c
1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003-2004 The OpenLDAP Foundation.
5  * Portions Copyright 2004 Pierangelo Masarati.
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 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by Pierangelo Masarati for inclusion
18  * in OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #include <stdio.h>
24
25 #include <ac/string.h>
26 #include <ac/socket.h>
27
28 #include "slap.h"
29 #include "back-relay.h"
30
31 static BackendDB *
32 relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
33 {
34         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
35         BackendDB               *bd = ri->ri_bd;
36
37         if ( bd == NULL ) {
38                 bd = select_backend( &op->o_req_ndn, 0, 1 );
39         }
40
41         if ( bd == NULL ) {
42                 if ( default_referral ) {
43                         rs->sr_ref = referral_rewrite( default_referral,
44                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
45                         if (!rs->sr_ref) {
46                                 rs->sr_ref = default_referral;
47                         }
48
49                         rs->sr_err = LDAP_REFERRAL;
50                         send_ldap_result( op, rs );
51
52                         if (rs->sr_ref != default_referral) {
53                                 ber_bvarray_free( rs->sr_ref );
54                         }
55
56                 } else {
57                         /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
58                          * LDAP_NO_SUCH_OBJECT for other operations.
59                          * noSuchObject is not allowed to be returned by bind */
60                         rs->sr_err = err;
61                         send_ldap_result( op, rs );
62                 }
63         }
64
65         return bd;
66 }
67
68 int
69 relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
70 {
71         BackendDB               *bd;
72         int                     rc = 1;
73
74         bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
75         if ( bd == NULL ) {
76                 return rc;
77         }
78
79         if ( bd->be_bind ) {
80                 BackendDB       *be = op->o_bd;
81
82                 op->o_bd = bd;
83                 rc = ( bd->be_bind )( op, rs );
84                 op->o_bd = be;
85
86         } else {
87                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
88                                 "operation not supported "
89                                 "within naming context" );
90         }
91
92         return rc;
93 }
94
95 int
96 relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
97 {
98         BackendDB               *bd;
99         int                     rc = 1;
100
101         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
102         if ( bd == NULL ) {
103                 return 1;
104         }
105
106         if ( bd->be_unbind ) {
107                 BackendDB       *be = op->o_bd;
108
109                 op->o_bd = bd;
110                 rc = ( bd->be_unbind )( op, rs );
111                 op->o_bd = be;
112
113         } else {
114                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
115                                 "operation not supported "
116                                 "within naming context" );
117         }
118
119         return rc;
120
121 }
122
123 int
124 relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
125 {
126         BackendDB               *bd;
127         int                     rc = 1;
128
129         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
130         if ( bd == NULL ) {
131                 return 1;
132         }
133
134         if ( bd->be_search ) {
135                 BackendDB       *be = op->o_bd;
136
137                 op->o_bd = bd;
138                 rc = ( bd->be_search )( op, rs );
139                 op->o_bd = be;
140
141         } else {
142                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
143                                 "operation not supported "
144                                 "within naming context" );
145         }
146
147         return rc;
148
149 }
150
151 int
152 relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
153 {
154         BackendDB               *bd;
155         int                     rc = 1;
156
157         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
158         if ( bd == NULL ) {
159                 return 1;
160         }
161
162         if ( bd->be_compare ) {
163                 BackendDB       *be = op->o_bd;
164
165                 op->o_bd = bd;
166                 rc = ( bd->be_compare )( op, rs );
167                 op->o_bd = be;
168
169         } else {
170                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
171                                 "operation not supported "
172                                 "within naming context" );
173         }
174
175         return rc;
176
177 }
178
179 int
180 relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
181 {
182         BackendDB               *bd;
183         int                     rc = 1;
184
185         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
186         if ( bd == NULL ) {
187                 return 1;
188         }
189
190         if ( bd->be_modify ) {
191                 BackendDB       *be = op->o_bd;
192
193                 op->o_bd = bd;
194                 rc = ( bd->be_modify )( op, rs );
195                 op->o_bd = be;
196
197         } else {
198                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
199                                 "operation not supported "
200                                 "within naming context" );
201         }
202
203         return rc;
204
205 }
206
207 int
208 relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
209 {
210         BackendDB               *bd;
211         int                     rc = 1;
212
213         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
214         if ( bd == NULL ) {
215                 return 1;
216         }
217
218         if ( bd->be_modrdn ) {
219                 BackendDB       *be = op->o_bd;
220
221                 op->o_bd = bd;
222                 rc = ( bd->be_modrdn )( op, rs );
223                 op->o_bd = be;
224
225         } else {
226                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
227                                 "operation not supported "
228                                 "within naming context" );
229         }
230
231         return rc;
232
233 }
234
235 int
236 relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
237 {
238         BackendDB               *bd;
239         int                     rc = 1;
240
241         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
242         if ( bd == NULL ) {
243                 return 1;
244         }
245
246         if ( bd->be_add ) {
247                 BackendDB       *be = op->o_bd;
248
249                 op->o_bd = bd;
250                 rc = ( bd->be_add )( op, rs );
251                 op->o_bd = be;
252
253         } else {
254                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
255                                 "operation not supported "
256                                 "within naming context" );
257         }
258
259         return rc;
260
261 }
262
263 int
264 relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
265 {
266         BackendDB               *bd;
267         int                     rc = 1;
268
269         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
270         if ( bd == NULL ) {
271                 return 1;
272         }
273
274         if ( bd->be_delete ) {
275                 BackendDB       *be = op->o_bd;
276
277                 op->o_bd = bd;
278                 rc = ( bd->be_delete )( op, rs );
279                 op->o_bd = be;
280         }
281
282         return rc;
283
284 }
285
286 int
287 relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
288 {
289         BackendDB               *bd;
290         int                     rc = 1;
291
292         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
293         if ( bd == NULL ) {
294                 return 1;
295         }
296
297         if ( bd->be_abandon ) {
298                 BackendDB       *be = op->o_bd;
299
300                 op->o_bd = bd;
301                 rc = ( bd->be_abandon )( op, rs );
302                 op->o_bd = be;
303
304         } else {
305                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
306                                 "operation not supported "
307                                 "within naming context" );
308         }
309
310         return rc;
311
312 }
313
314 int
315 relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
316 {
317         BackendDB               *bd;
318         int                     rc = 1;
319
320         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
321         if ( bd == NULL ) {
322                 return 1;
323         }
324
325         if ( bd->be_cancel ) {
326                 BackendDB       *be = op->o_bd;
327
328                 op->o_bd = bd;
329                 rc = ( bd->be_cancel )( op, rs );
330                 op->o_bd = be;
331
332         } else {
333                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
334                                 "operation not supported "
335                                 "within naming context" );
336         }
337
338         return rc;
339
340 }
341
342 int
343 relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
344 {
345         BackendDB               *bd;
346         int                     rc = 1;
347
348         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
349         if ( bd == NULL ) {
350                 return 1;
351         }
352
353         if ( bd->be_extended ) {
354                 BackendDB       *be = op->o_bd;
355
356                 op->o_bd = bd;
357                 rc = ( bd->be_extended )( op, rs );
358                 op->o_bd = be;
359
360         } else {
361                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
362                                 "operation not supported "
363                                 "within naming context" );
364         }
365
366         return rc;
367
368 }
369
370 int
371 relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
372 {
373         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
374         BackendDB               *bd;
375         int                     rc = 1;
376
377         bd = ri->ri_bd;
378         if ( bd == NULL) {
379                 bd = select_backend( &op->o_req_ndn, 0, 1 );
380                 if ( bd == NULL ) {
381                         return 1;
382                 }
383         }
384
385         if ( bd->be_release ) {
386                 BackendDB       *be = op->o_bd;
387
388                 op->o_bd = bd;
389                 rc = ( bd->be_release )( op, e, rw );
390                 op->o_bd = be;
391         }
392
393         return rc;
394
395 }
396
397 int
398 relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
399         ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
400 {
401         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
402         BackendDB               *bd;
403         int                     rc = 1;
404
405         bd = ri->ri_bd;
406         if ( bd == NULL) {
407                 bd = select_backend( &op->o_req_ndn, 0, 1 );
408                 if ( bd == NULL ) {
409                         return 1;
410                 }
411         }
412
413         if ( bd->be_fetch ) {
414                 BackendDB       *be = op->o_bd;
415
416                 op->o_bd = bd;
417                 rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
418                 op->o_bd = be;
419         }
420
421         return rc;
422
423 }
424
425 int
426 relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
427 {
428         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
429         BackendDB               *bd;
430         int                     rc = 1;
431
432         bd = ri->ri_bd;
433         if ( bd == NULL) {
434                 bd = select_backend( &op->o_req_ndn, 0, 1 );
435                 if ( bd == NULL ) {
436                         return 1;
437                 }
438         }
439
440         if ( bd->be_chk_referrals ) {
441                 BackendDB       *be = op->o_bd;
442
443                 op->o_bd = bd;
444                 rc = ( bd->be_chk_referrals )( op, rs );
445                 op->o_bd = be;
446         }
447
448         return rc;
449
450 }
451
452 int
453 relay_back_operational( struct slap_op *op, struct slap_rep *rs, 
454                 int opattrs, Attribute **ap )
455 {
456         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
457         BackendDB               *bd;
458         int                     rc = 1;
459
460         bd = ri->ri_bd;
461         if ( bd == NULL) {
462                 bd = select_backend( &op->o_req_ndn, 0, 1 );
463                 if ( bd == NULL ) {
464                         return 1;
465                 }
466         }
467
468         if ( bd->be_operational ) {
469                 BackendDB       *be = op->o_bd;
470
471                 op->o_bd = bd;
472                 rc = ( bd->be_operational )( op, rs, opattrs, ap );
473                 op->o_bd = be;
474         }
475
476         return rc;
477
478 }
479
480 int
481 relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
482 {
483         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
484         BackendDB               *bd;
485         int                     rc = 1;
486
487         bd = ri->ri_bd;
488         if ( bd == NULL) {
489                 bd = select_backend( &op->o_req_ndn, 0, 1 );
490                 if ( bd == NULL ) {
491                         return 1;
492                 }
493         }
494
495         if ( bd->be_has_subordinates ) {
496                 BackendDB       *be = op->o_bd;
497
498                 op->o_bd = bd;
499                 rc = ( bd->be_has_subordinates )( op, e, hasSubs );
500                 op->o_bd = be;
501         }
502
503         return rc;
504
505 }
506
507 int
508 relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
509 {
510         relay_back_info         *ri = (relay_back_info *)bd->be_private;
511
512         if ( ri->ri_bd->be_connection_init ) {
513                 return ( ri->ri_bd->be_connection_init )( ri->ri_bd, c );
514         }
515
516         return 1;
517
518 }
519
520 int
521 relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
522 {
523         relay_back_info         *ri = (relay_back_info *)bd->be_private;
524
525         if ( ri->ri_bd->be_connection_destroy ) {
526                 return ( ri->ri_bd->be_connection_destroy )( ri->ri_bd, c );
527         }
528
529         return 1;
530
531 }
532
533 /*
534  * FIXME: must implement tools as well
535  */