distproc.c revision 1.1 1 1.1 lukem /* distproc.c - implement distributed procedures */
2 1.1 lukem /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/distproc.c,v 1.3.2.7 2008/02/12 00:58:15 quanah Exp $ */
3 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 1.1 lukem *
5 1.1 lukem * Copyright 2005-2008 The OpenLDAP Foundation.
6 1.1 lukem * Portions Copyright 2003 Howard Chu.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem /* ACKNOWLEDGEMENTS:
18 1.1 lukem * This work was initially developed by Pierangelo Masarati for inclusion
19 1.1 lukem * in OpenLDAP Software.
20 1.1 lukem * Based on back-ldap and slapo-chain, developed by Howard Chu
21 1.1 lukem */
22 1.1 lukem
23 1.1 lukem #include "portable.h"
24 1.1 lukem
25 1.1 lukem #include <stdio.h>
26 1.1 lukem
27 1.1 lukem #include <ac/string.h>
28 1.1 lukem #include <ac/socket.h>
29 1.1 lukem
30 1.1 lukem #include "slap.h"
31 1.1 lukem
32 1.1 lukem #ifdef SLAP_DISTPROC
33 1.1 lukem
34 1.1 lukem #include "back-ldap.h"
35 1.1 lukem
36 1.1 lukem #include "config.h"
37 1.1 lukem
38 1.1 lukem /*
39 1.1 lukem * From <draft-sermersheim-ldap-distproc>
40 1.1 lukem *
41 1.1 lukem
42 1.1 lukem ContinuationReference ::= SET {
43 1.1 lukem referralURI [0] SET SIZE (1..MAX) OF URI,
44 1.1 lukem localReference [2] LDAPDN,
45 1.1 lukem referenceType [3] ReferenceType,
46 1.1 lukem remainingName [4] RelativeLDAPDN OPTIONAL,
47 1.1 lukem searchScope [5] SearchScope OPTIONAL,
48 1.1 lukem searchedSubtrees [6] SearchedSubtrees OPTIONAL,
49 1.1 lukem failedName [7] LDAPDN OPTIONAL,
50 1.1 lukem ... }
51 1.1 lukem
52 1.1 lukem ReferenceType ::= ENUMERATED {
53 1.1 lukem superior (0),
54 1.1 lukem subordinate (1),
55 1.1 lukem cross (2),
56 1.1 lukem nonSpecificSubordinate (3),
57 1.1 lukem supplier (4),
58 1.1 lukem master (5),
59 1.1 lukem immediateSuperior (6),
60 1.1 lukem self (7),
61 1.1 lukem ... }
62 1.1 lukem
63 1.1 lukem SearchScope ::= ENUMERATED {
64 1.1 lukem baseObject (0),
65 1.1 lukem singleLevel (1),
66 1.1 lukem wholeSubtree (2),
67 1.1 lukem subordinateSubtree (3),
68 1.1 lukem ... }
69 1.1 lukem
70 1.1 lukem SearchedSubtrees ::= SET OF RelativeLDAPDN
71 1.1 lukem
72 1.1 lukem LDAPDN, RelativeLDAPDN, and LDAPString, are defined in [RFC2251].
73 1.1 lukem
74 1.1 lukem */
75 1.1 lukem
76 1.1 lukem typedef enum ReferenceType_t {
77 1.1 lukem LDAP_DP_RT_UNKNOWN = -1,
78 1.1 lukem LDAP_DP_RT_SUPERIOR = 0,
79 1.1 lukem LDAP_DP_RT_SUBORDINATE = 1,
80 1.1 lukem LDAP_DP_RT_CROSS = 2,
81 1.1 lukem LDAP_DP_RT_NONSPECIFICSUBORDINATE = 3,
82 1.1 lukem LDAP_DP_RT_SUPPLIER = 4,
83 1.1 lukem LDAP_DP_RT_MASTER = 5,
84 1.1 lukem LDAP_DP_RT_IMMEDIATESUPERIOR = 6,
85 1.1 lukem LDAP_DP_RT_SELF = 7,
86 1.1 lukem LDAP_DP_RT_LAST
87 1.1 lukem } ReferenceType_t;
88 1.1 lukem
89 1.1 lukem typedef enum SearchScope_t {
90 1.1 lukem LDAP_DP_SS_UNKNOWN = -1,
91 1.1 lukem LDAP_DP_SS_BASEOBJECT = 0,
92 1.1 lukem LDAP_DP_SS_SINGLELEVEL = 1,
93 1.1 lukem LDAP_DP_SS_WHOLESUBTREE = 2,
94 1.1 lukem LDAP_DP_SS_SUBORDINATESUBTREE = 3,
95 1.1 lukem LDAP_DP_SS_LAST
96 1.1 lukem } SearchScope_t;
97 1.1 lukem
98 1.1 lukem typedef struct ContinuationReference_t {
99 1.1 lukem BerVarray cr_referralURI;
100 1.1 lukem /* ? [1] ? */
101 1.1 lukem struct berval cr_localReference;
102 1.1 lukem ReferenceType_t cr_referenceType;
103 1.1 lukem struct berval cr_remainingName;
104 1.1 lukem SearchScope_t cr_searchScope;
105 1.1 lukem BerVarray cr_searchedSubtrees;
106 1.1 lukem struct berval cr_failedName;
107 1.1 lukem } ContinuationReference_t;
108 1.1 lukem #define CR_INIT { NULL, BER_BVNULL, LDAP_DP_RT_UNKNOWN, BER_BVNULL, LDAP_DP_SS_UNKNOWN, NULL, BER_BVNULL }
109 1.1 lukem
110 1.1 lukem static struct berval bv2rt[] = {
111 1.1 lukem BER_BVC( "superior" ),
112 1.1 lukem BER_BVC( "subordinate" ),
113 1.1 lukem BER_BVC( "cross" ),
114 1.1 lukem BER_BVC( "nonSpecificSubordinate" ),
115 1.1 lukem BER_BVC( "supplier" ),
116 1.1 lukem BER_BVC( "master" ),
117 1.1 lukem BER_BVC( "immediateSuperior" ),
118 1.1 lukem BER_BVC( "self" ),
119 1.1 lukem BER_BVNULL
120 1.1 lukem };
121 1.1 lukem
122 1.1 lukem static struct berval bv2ss[] = {
123 1.1 lukem BER_BVC( "baseObject" ),
124 1.1 lukem BER_BVC( "singleLevel" ),
125 1.1 lukem BER_BVC( "wholeSubtree" ),
126 1.1 lukem BER_BVC( "subordinateSubtree" ),
127 1.1 lukem BER_BVNULL
128 1.1 lukem };
129 1.1 lukem
130 1.1 lukem static struct berval *
131 1.1 lukem ldap_distproc_rt2bv( ReferenceType_t rt )
132 1.1 lukem {
133 1.1 lukem return &bv2rt[ rt ];
134 1.1 lukem }
135 1.1 lukem
136 1.1 lukem static const char *
137 1.1 lukem ldap_distproc_rt2str( ReferenceType_t rt )
138 1.1 lukem {
139 1.1 lukem return bv2rt[ rt ].bv_val;
140 1.1 lukem }
141 1.1 lukem
142 1.1 lukem static ReferenceType_t
143 1.1 lukem ldap_distproc_bv2rt( struct berval *bv )
144 1.1 lukem {
145 1.1 lukem ReferenceType_t rt;
146 1.1 lukem
147 1.1 lukem for ( rt = 0; !BER_BVISNULL( &bv2rt[ rt ] ); rt++ ) {
148 1.1 lukem if ( ber_bvstrcasecmp( bv, &bv2rt[ rt ] ) == 0 ) {
149 1.1 lukem return rt;
150 1.1 lukem }
151 1.1 lukem }
152 1.1 lukem
153 1.1 lukem return LDAP_DP_RT_UNKNOWN;
154 1.1 lukem }
155 1.1 lukem
156 1.1 lukem static ReferenceType_t
157 1.1 lukem ldap_distproc_str2rt( const char *s )
158 1.1 lukem {
159 1.1 lukem struct berval bv;
160 1.1 lukem
161 1.1 lukem ber_str2bv( s, 0, 0, &bv );
162 1.1 lukem return ldap_distproc_bv2rt( &bv );
163 1.1 lukem }
164 1.1 lukem
165 1.1 lukem static struct berval *
166 1.1 lukem ldap_distproc_ss2bv( SearchScope_t ss )
167 1.1 lukem {
168 1.1 lukem return &bv2ss[ ss ];
169 1.1 lukem }
170 1.1 lukem
171 1.1 lukem static const char *
172 1.1 lukem ldap_distproc_ss2str( SearchScope_t ss )
173 1.1 lukem {
174 1.1 lukem return bv2ss[ ss ].bv_val;
175 1.1 lukem }
176 1.1 lukem
177 1.1 lukem static SearchScope_t
178 1.1 lukem ldap_distproc_bv2ss( struct berval *bv )
179 1.1 lukem {
180 1.1 lukem ReferenceType_t ss;
181 1.1 lukem
182 1.1 lukem for ( ss = 0; !BER_BVISNULL( &bv2ss[ ss ] ); ss++ ) {
183 1.1 lukem if ( ber_bvstrcasecmp( bv, &bv2ss[ ss ] ) == 0 ) {
184 1.1 lukem return ss;
185 1.1 lukem }
186 1.1 lukem }
187 1.1 lukem
188 1.1 lukem return LDAP_DP_SS_UNKNOWN;
189 1.1 lukem }
190 1.1 lukem
191 1.1 lukem static SearchScope_t
192 1.1 lukem ldap_distproc_str2ss( const char *s )
193 1.1 lukem {
194 1.1 lukem struct berval bv;
195 1.1 lukem
196 1.1 lukem ber_str2bv( s, 0, 0, &bv );
197 1.1 lukem return ldap_distproc_bv2ss( &bv );
198 1.1 lukem }
199 1.1 lukem
200 1.1 lukem /*
201 1.1 lukem * NOTE: this overlay assumes that the chainingBehavior control
202 1.1 lukem * is registered by the chain overlay; it may move here some time.
203 1.1 lukem * This overlay provides support for that control as well.
204 1.1 lukem */
205 1.1 lukem
206 1.1 lukem
207 1.1 lukem static int sc_returnContRef;
208 1.1 lukem #define o_returnContRef o_ctrlflag[sc_returnContRef]
209 1.1 lukem #define get_returnContRef(op) ((op)->o_returnContRef & SLAP_CONTROL_MASK)
210 1.1 lukem
211 1.1 lukem static struct berval slap_EXOP_CHAINEDREQUEST = BER_BVC( LDAP_EXOP_X_CHAINEDREQUEST );
212 1.1 lukem static struct berval slap_FEATURE_CANCHAINOPS = BER_BVC( LDAP_FEATURE_X_CANCHAINOPS );
213 1.1 lukem
214 1.1 lukem static BackendInfo *lback;
215 1.1 lukem
216 1.1 lukem typedef struct ldap_distproc_t {
217 1.1 lukem /* "common" configuration info (anything occurring before an "uri") */
218 1.1 lukem ldapinfo_t *lc_common_li;
219 1.1 lukem
220 1.1 lukem /* current configuration info */
221 1.1 lukem ldapinfo_t *lc_cfg_li;
222 1.1 lukem
223 1.1 lukem /* tree of configured[/generated?] "uri" info */
224 1.1 lukem ldap_avl_info_t lc_lai;
225 1.1 lukem
226 1.1 lukem unsigned lc_flags;
227 1.1 lukem #define LDAP_DISTPROC_F_NONE (0x00U)
228 1.1 lukem #define LDAP_DISTPROC_F_CHAINING (0x01U)
229 1.1 lukem #define LDAP_DISTPROC_F_CACHE_URI (0x10U)
230 1.1 lukem
231 1.1 lukem #define LDAP_DISTPROC_CHAINING( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CHAINING ) == LDAP_DISTPROC_F_CHAINING )
232 1.1 lukem #define LDAP_DISTPROC_CACHE_URI( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CACHE_URI ) == LDAP_DISTPROC_F_CACHE_URI )
233 1.1 lukem
234 1.1 lukem } ldap_distproc_t;
235 1.1 lukem
236 1.1 lukem static int ldap_distproc_db_init_common( BackendDB *be );
237 1.1 lukem static int ldap_distproc_db_init_one( BackendDB *be );
238 1.1 lukem #define ldap_distproc_db_open_one(be) (lback)->bi_db_open( (be) )
239 1.1 lukem #define ldap_distproc_db_close_one(be) (0)
240 1.1 lukem #define ldap_distproc_db_destroy_one(be, ca) (lback)->bi_db_destroy( (be), (ca) )
241 1.1 lukem
242 1.1 lukem static int
243 1.1 lukem ldap_distproc_parse_ctrl(
244 1.1 lukem Operation *op,
245 1.1 lukem SlapReply *rs,
246 1.1 lukem LDAPControl *ctrl );
247 1.1 lukem
248 1.1 lukem static int
249 1.1 lukem ldap_distproc_uri_cmp( const void *c1, const void *c2 )
250 1.1 lukem {
251 1.1 lukem const ldapinfo_t *li1 = (const ldapinfo_t *)c1;
252 1.1 lukem const ldapinfo_t *li2 = (const ldapinfo_t *)c2;
253 1.1 lukem
254 1.1 lukem assert( li1->li_bvuri != NULL );
255 1.1 lukem assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) );
256 1.1 lukem assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) );
257 1.1 lukem
258 1.1 lukem assert( li2->li_bvuri != NULL );
259 1.1 lukem assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
260 1.1 lukem assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
261 1.1 lukem
262 1.1 lukem /* If local DNs don't match, it is definitely not a match */
263 1.1 lukem return ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] );
264 1.1 lukem }
265 1.1 lukem
266 1.1 lukem static int
267 1.1 lukem ldap_distproc_uri_dup( void *c1, void *c2 )
268 1.1 lukem {
269 1.1 lukem ldapinfo_t *li1 = (ldapinfo_t *)c1;
270 1.1 lukem ldapinfo_t *li2 = (ldapinfo_t *)c2;
271 1.1 lukem
272 1.1 lukem assert( li1->li_bvuri != NULL );
273 1.1 lukem assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) );
274 1.1 lukem assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) );
275 1.1 lukem
276 1.1 lukem assert( li2->li_bvuri != NULL );
277 1.1 lukem assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
278 1.1 lukem assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
279 1.1 lukem
280 1.1 lukem /* Cannot have more than one shared session with same DN */
281 1.1 lukem if ( ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ) == 0 ) {
282 1.1 lukem return -1;
283 1.1 lukem }
284 1.1 lukem
285 1.1 lukem return 0;
286 1.1 lukem }
287 1.1 lukem
288 1.1 lukem static int
289 1.1 lukem ldap_distproc_operational( Operation *op, SlapReply *rs )
290 1.1 lukem {
291 1.1 lukem /* Trap entries generated by back-ldap.
292 1.1 lukem *
293 1.1 lukem * FIXME: we need a better way to recognize them; a cleaner
294 1.1 lukem * solution would be to be able to intercept the response
295 1.1 lukem * of be_operational(), so that we can divert only those
296 1.1 lukem * calls that fail because operational attributes were
297 1.1 lukem * requested for entries that do not belong to the underlying
298 1.1 lukem * database. This fix is likely to intercept also entries
299 1.1 lukem * generated by back-perl and so. */
300 1.1 lukem if ( rs->sr_entry->e_private == NULL ) {
301 1.1 lukem return LDAP_SUCCESS;
302 1.1 lukem }
303 1.1 lukem
304 1.1 lukem return SLAP_CB_CONTINUE;
305 1.1 lukem }
306 1.1 lukem
307 1.1 lukem static int
308 1.1 lukem ldap_distproc_response( Operation *op, SlapReply *rs )
309 1.1 lukem {
310 1.1 lukem return SLAP_CB_CONTINUE;
311 1.1 lukem }
312 1.1 lukem
313 1.1 lukem /*
314 1.1 lukem * configuration...
315 1.1 lukem */
316 1.1 lukem
317 1.1 lukem enum {
318 1.1 lukem /* NOTE: the chaining behavior control is registered
319 1.1 lukem * by the chain overlay; it may move here some time */
320 1.1 lukem DP_CHAINING = 1,
321 1.1 lukem DP_CACHE_URI,
322 1.1 lukem
323 1.1 lukem DP_LAST
324 1.1 lukem };
325 1.1 lukem
326 1.1 lukem static ConfigDriver distproc_cfgen;
327 1.1 lukem static ConfigCfAdd distproc_cfadd;
328 1.1 lukem static ConfigLDAPadd distproc_ldadd;
329 1.1 lukem
330 1.1 lukem static ConfigTable distproc_cfg[] = {
331 1.1 lukem { "distproc-chaining", "args",
332 1.1 lukem 2, 4, 0, ARG_MAGIC|ARG_BERVAL|DP_CHAINING, distproc_cfgen,
333 1.1 lukem /* NOTE: using the same attributeTypes defined
334 1.1 lukem * for the "chain" overlay */
335 1.1 lukem "( OLcfgOvAt:3.1 NAME 'olcChainingBehavior' "
336 1.1 lukem "DESC 'Chaining behavior control parameters (draft-sermersheim-ldap-chaining)' "
337 1.1 lukem "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
338 1.1 lukem { "distproc-cache-uri", "TRUE/FALSE",
339 1.1 lukem 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|DP_CACHE_URI, distproc_cfgen,
340 1.1 lukem "( OLcfgOvAt:3.2 NAME 'olcChainCacheURI' "
341 1.1 lukem "DESC 'Enables caching of URIs not present in configuration' "
342 1.1 lukem "SYNTAX OMsBoolean "
343 1.1 lukem "SINGLE-VALUE )", NULL, NULL },
344 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED }
345 1.1 lukem };
346 1.1 lukem
347 1.1 lukem static ConfigOCs distproc_ocs[] = {
348 1.1 lukem { "( OLcfgOvOc:7.1 "
349 1.1 lukem "NAME 'olcDistProcConfig' "
350 1.1 lukem "DESC 'Distributed procedures <draft-sermersheim-ldap-distproc> configuration' "
351 1.1 lukem "SUP olcOverlayConfig "
352 1.1 lukem "MAY ( "
353 1.1 lukem "olcChainingBehavior $ "
354 1.1 lukem "olcChainCacheURI "
355 1.1 lukem ") )",
356 1.1 lukem Cft_Overlay, distproc_cfg, NULL, distproc_cfadd },
357 1.1 lukem { "( OLcfgOvOc:7.2 "
358 1.1 lukem "NAME 'olcDistProcDatabase' "
359 1.1 lukem "DESC 'Distributed procedure remote server configuration' "
360 1.1 lukem "AUXILIARY )",
361 1.1 lukem Cft_Misc, distproc_cfg, distproc_ldadd },
362 1.1 lukem { NULL, 0, NULL }
363 1.1 lukem };
364 1.1 lukem
365 1.1 lukem static int
366 1.1 lukem distproc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
367 1.1 lukem {
368 1.1 lukem slap_overinst *on;
369 1.1 lukem ldap_distproc_t *lc;
370 1.1 lukem
371 1.1 lukem ldapinfo_t *li;
372 1.1 lukem
373 1.1 lukem AttributeDescription *ad = NULL;
374 1.1 lukem Attribute *at;
375 1.1 lukem const char *text;
376 1.1 lukem
377 1.1 lukem int rc;
378 1.1 lukem
379 1.1 lukem if ( p->ce_type != Cft_Overlay
380 1.1 lukem || !p->ce_bi
381 1.1 lukem || p->ce_bi->bi_cf_ocs != distproc_ocs )
382 1.1 lukem {
383 1.1 lukem return LDAP_CONSTRAINT_VIOLATION;
384 1.1 lukem }
385 1.1 lukem
386 1.1 lukem on = (slap_overinst *)p->ce_bi;
387 1.1 lukem lc = (ldap_distproc_t *)on->on_bi.bi_private;
388 1.1 lukem
389 1.1 lukem assert( ca->be == NULL );
390 1.1 lukem ca->be = (BackendDB *)ch_calloc( 1, sizeof( BackendDB ) );
391 1.1 lukem
392 1.1 lukem ca->be->bd_info = (BackendInfo *)on;
393 1.1 lukem
394 1.1 lukem rc = slap_str2ad( "olcDbURI", &ad, &text );
395 1.1 lukem assert( rc == LDAP_SUCCESS );
396 1.1 lukem
397 1.1 lukem at = attr_find( e->e_attrs, ad );
398 1.1 lukem if ( lc->lc_common_li == NULL && at != NULL ) {
399 1.1 lukem /* FIXME: we should generate an empty default entry
400 1.1 lukem * if none is supplied */
401 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
402 1.1 lukem "first underlying database \"%s\" "
403 1.1 lukem "cannot contain attribute \"%s\".\n",
404 1.1 lukem e->e_name.bv_val, ad->ad_cname.bv_val, 0 );
405 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION;
406 1.1 lukem goto done;
407 1.1 lukem
408 1.1 lukem } else if ( lc->lc_common_li != NULL && at == NULL ) {
409 1.1 lukem /* FIXME: we should generate an empty default entry
410 1.1 lukem * if none is supplied */
411 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
412 1.1 lukem "subsequent underlying database \"%s\" "
413 1.1 lukem "must contain attribute \"%s\".\n",
414 1.1 lukem e->e_name.bv_val, ad->ad_cname.bv_val, 0 );
415 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION;
416 1.1 lukem goto done;
417 1.1 lukem }
418 1.1 lukem
419 1.1 lukem if ( lc->lc_common_li == NULL ) {
420 1.1 lukem rc = ldap_distproc_db_init_common( ca->be );
421 1.1 lukem
422 1.1 lukem } else {
423 1.1 lukem rc = ldap_distproc_db_init_one( ca->be );
424 1.1 lukem }
425 1.1 lukem
426 1.1 lukem if ( rc != 0 ) {
427 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
428 1.1 lukem "unable to init %sunderlying database \"%s\".\n",
429 1.1 lukem lc->lc_common_li == NULL ? "common " : "", e->e_name.bv_val, 0 );
430 1.1 lukem return LDAP_CONSTRAINT_VIOLATION;
431 1.1 lukem }
432 1.1 lukem
433 1.1 lukem li = ca->be->be_private;
434 1.1 lukem
435 1.1 lukem if ( lc->lc_common_li == NULL ) {
436 1.1 lukem lc->lc_common_li = li;
437 1.1 lukem
438 1.1 lukem } else if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li,
439 1.1 lukem ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) )
440 1.1 lukem {
441 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
442 1.1 lukem "database \"%s\" insert failed.\n",
443 1.1 lukem e->e_name.bv_val, 0, 0 );
444 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION;
445 1.1 lukem goto done;
446 1.1 lukem }
447 1.1 lukem
448 1.1 lukem done:;
449 1.1 lukem if ( rc != LDAP_SUCCESS ) {
450 1.1 lukem (void)ldap_distproc_db_destroy_one( ca->be, NULL );
451 1.1 lukem ch_free( ca->be );
452 1.1 lukem ca->be = NULL;
453 1.1 lukem }
454 1.1 lukem
455 1.1 lukem return rc;
456 1.1 lukem }
457 1.1 lukem
458 1.1 lukem typedef struct ldap_distproc_cfadd_apply_t {
459 1.1 lukem Operation *op;
460 1.1 lukem SlapReply *rs;
461 1.1 lukem Entry *p;
462 1.1 lukem ConfigArgs *ca;
463 1.1 lukem int count;
464 1.1 lukem } ldap_distproc_cfadd_apply_t;
465 1.1 lukem
466 1.1 lukem static int
467 1.1 lukem ldap_distproc_cfadd_apply( void *datum, void *arg )
468 1.1 lukem {
469 1.1 lukem ldapinfo_t *li = (ldapinfo_t *)datum;
470 1.1 lukem ldap_distproc_cfadd_apply_t *lca = (ldap_distproc_cfadd_apply_t *)arg;
471 1.1 lukem
472 1.1 lukem struct berval bv;
473 1.1 lukem
474 1.1 lukem /* FIXME: should not hardcode "olcDatabase" here */
475 1.1 lukem bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
476 1.1 lukem "olcDatabase={%d}%s", lca->count, lback->bi_type );
477 1.1 lukem bv.bv_val = lca->ca->cr_msg;
478 1.1 lukem
479 1.1 lukem lca->ca->be->be_private = (void *)li;
480 1.1 lukem config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
481 1.1 lukem &bv, lback->bi_cf_ocs, &distproc_ocs[ 1 ] );
482 1.1 lukem
483 1.1 lukem lca->count++;
484 1.1 lukem
485 1.1 lukem return 0;
486 1.1 lukem }
487 1.1 lukem
488 1.1 lukem static int
489 1.1 lukem distproc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )
490 1.1 lukem {
491 1.1 lukem CfEntryInfo *pe = p->e_private;
492 1.1 lukem slap_overinst *on = (slap_overinst *)pe->ce_bi;
493 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
494 1.1 lukem void *priv = (void *)ca->be->be_private;
495 1.1 lukem
496 1.1 lukem if ( lback->bi_cf_ocs ) {
497 1.1 lukem ldap_distproc_cfadd_apply_t lca = { 0 };
498 1.1 lukem
499 1.1 lukem lca.op = op;
500 1.1 lukem lca.rs = rs;
501 1.1 lukem lca.p = p;
502 1.1 lukem lca.ca = ca;
503 1.1 lukem lca.count = 0;
504 1.1 lukem
505 1.1 lukem (void)ldap_distproc_cfadd_apply( (void *)lc->lc_common_li, (void *)&lca );
506 1.1 lukem
507 1.1 lukem (void)avl_apply( lc->lc_lai.lai_tree, ldap_distproc_cfadd_apply,
508 1.1 lukem &lca, 1, AVL_INORDER );
509 1.1 lukem
510 1.1 lukem ca->be->be_private = priv;
511 1.1 lukem }
512 1.1 lukem
513 1.1 lukem return 0;
514 1.1 lukem }
515 1.1 lukem
516 1.1 lukem static int
517 1.1 lukem distproc_cfgen( ConfigArgs *c )
518 1.1 lukem {
519 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
520 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
521 1.1 lukem
522 1.1 lukem int rc = 0;
523 1.1 lukem
524 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) {
525 1.1 lukem switch( c->type ) {
526 1.1 lukem case DP_CACHE_URI:
527 1.1 lukem c->value_int = LDAP_DISTPROC_CACHE_URI( lc );
528 1.1 lukem break;
529 1.1 lukem
530 1.1 lukem default:
531 1.1 lukem assert( 0 );
532 1.1 lukem rc = 1;
533 1.1 lukem }
534 1.1 lukem return rc;
535 1.1 lukem
536 1.1 lukem } else if ( c->op == LDAP_MOD_DELETE ) {
537 1.1 lukem switch( c->type ) {
538 1.1 lukem case DP_CHAINING:
539 1.1 lukem return 1;
540 1.1 lukem
541 1.1 lukem case DP_CACHE_URI:
542 1.1 lukem lc->lc_flags &= ~LDAP_DISTPROC_F_CACHE_URI;
543 1.1 lukem break;
544 1.1 lukem
545 1.1 lukem default:
546 1.1 lukem return 1;
547 1.1 lukem }
548 1.1 lukem return rc;
549 1.1 lukem }
550 1.1 lukem
551 1.1 lukem switch( c->type ) {
552 1.1 lukem case DP_CACHE_URI:
553 1.1 lukem if ( c->value_int ) {
554 1.1 lukem lc->lc_flags |= LDAP_DISTPROC_F_CACHE_URI;
555 1.1 lukem } else {
556 1.1 lukem lc->lc_flags &= ~LDAP_DISTPROC_F_CACHE_URI;
557 1.1 lukem }
558 1.1 lukem break;
559 1.1 lukem
560 1.1 lukem default:
561 1.1 lukem assert( 0 );
562 1.1 lukem return 1;
563 1.1 lukem }
564 1.1 lukem
565 1.1 lukem return rc;
566 1.1 lukem }
567 1.1 lukem
568 1.1 lukem static int
569 1.1 lukem ldap_distproc_db_init(
570 1.1 lukem BackendDB *be,
571 1.1 lukem ConfigReply *cr )
572 1.1 lukem {
573 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
574 1.1 lukem ldap_distproc_t *lc = NULL;
575 1.1 lukem
576 1.1 lukem if ( lback == NULL ) {
577 1.1 lukem lback = backend_info( "ldap" );
578 1.1 lukem
579 1.1 lukem if ( lback == NULL ) {
580 1.1 lukem return 1;
581 1.1 lukem }
582 1.1 lukem }
583 1.1 lukem
584 1.1 lukem lc = ch_malloc( sizeof( ldap_distproc_t ) );
585 1.1 lukem if ( lc == NULL ) {
586 1.1 lukem return 1;
587 1.1 lukem }
588 1.1 lukem memset( lc, 0, sizeof( ldap_distproc_t ) );
589 1.1 lukem ldap_pvt_thread_mutex_init( &lc->lc_lai.lai_mutex );
590 1.1 lukem
591 1.1 lukem on->on_bi.bi_private = (void *)lc;
592 1.1 lukem
593 1.1 lukem return 0;
594 1.1 lukem }
595 1.1 lukem
596 1.1 lukem static int
597 1.1 lukem ldap_distproc_db_config(
598 1.1 lukem BackendDB *be,
599 1.1 lukem const char *fname,
600 1.1 lukem int lineno,
601 1.1 lukem int argc,
602 1.1 lukem char **argv )
603 1.1 lukem {
604 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
605 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
606 1.1 lukem
607 1.1 lukem int rc = SLAP_CONF_UNKNOWN;
608 1.1 lukem
609 1.1 lukem if ( lc->lc_common_li == NULL ) {
610 1.1 lukem void *be_private = be->be_private;
611 1.1 lukem ldap_distproc_db_init_common( be );
612 1.1 lukem lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)be->be_private;
613 1.1 lukem be->be_private = be_private;
614 1.1 lukem }
615 1.1 lukem
616 1.1 lukem /* Something for the distproc database? */
617 1.1 lukem if ( strncasecmp( argv[ 0 ], "distproc-", STRLENOF( "distproc-" ) ) == 0 ) {
618 1.1 lukem char *save_argv0 = argv[ 0 ];
619 1.1 lukem BackendInfo *bd_info = be->bd_info;
620 1.1 lukem void *be_private = be->be_private;
621 1.1 lukem ConfigOCs *be_cf_ocs = be->be_cf_ocs;
622 1.1 lukem int is_uri = 0;
623 1.1 lukem
624 1.1 lukem argv[ 0 ] += STRLENOF( "distproc-" );
625 1.1 lukem
626 1.1 lukem if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) {
627 1.1 lukem rc = ldap_distproc_db_init_one( be );
628 1.1 lukem if ( rc != 0 ) {
629 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: "
630 1.1 lukem "underlying slapd-ldap initialization failed.\n.",
631 1.1 lukem fname, lineno, 0 );
632 1.1 lukem return 1;
633 1.1 lukem }
634 1.1 lukem lc->lc_cfg_li = be->be_private;
635 1.1 lukem is_uri = 1;
636 1.1 lukem }
637 1.1 lukem
638 1.1 lukem /* TODO: add checks on what other slapd-ldap(5) args
639 1.1 lukem * should be put in the template; this is not quite
640 1.1 lukem * harmful, because attributes that shouldn't don't
641 1.1 lukem * get actually used, but the user should at least
642 1.1 lukem * be warned.
643 1.1 lukem */
644 1.1 lukem
645 1.1 lukem be->bd_info = lback;
646 1.1 lukem be->be_private = (void *)lc->lc_cfg_li;
647 1.1 lukem be->be_cf_ocs = lback->bi_cf_ocs;
648 1.1 lukem
649 1.1 lukem rc = config_generic_wrapper( be, fname, lineno, argc, argv );
650 1.1 lukem
651 1.1 lukem argv[ 0 ] = save_argv0;
652 1.1 lukem be->be_cf_ocs = be_cf_ocs;
653 1.1 lukem be->be_private = be_private;
654 1.1 lukem be->bd_info = bd_info;
655 1.1 lukem
656 1.1 lukem if ( is_uri ) {
657 1.1 lukem private_destroy:;
658 1.1 lukem if ( rc != 0 ) {
659 1.1 lukem BackendDB db = *be;
660 1.1 lukem
661 1.1 lukem db.bd_info = lback;
662 1.1 lukem db.be_private = (void *)lc->lc_cfg_li;
663 1.1 lukem ldap_distproc_db_destroy_one( &db, NULL );
664 1.1 lukem lc->lc_cfg_li = NULL;
665 1.1 lukem
666 1.1 lukem } else {
667 1.1 lukem if ( lc->lc_cfg_li->li_bvuri == NULL
668 1.1 lukem || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] )
669 1.1 lukem || !BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 1 ] ) )
670 1.1 lukem {
671 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: "
672 1.1 lukem "no URI list allowed in slapo-distproc.\n",
673 1.1 lukem fname, lineno, 0 );
674 1.1 lukem rc = 1;
675 1.1 lukem goto private_destroy;
676 1.1 lukem }
677 1.1 lukem
678 1.1 lukem if ( avl_insert( &lc->lc_lai.lai_tree,
679 1.1 lukem (caddr_t)lc->lc_cfg_li,
680 1.1 lukem ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) )
681 1.1 lukem {
682 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: "
683 1.1 lukem "duplicate URI in slapo-distproc.\n",
684 1.1 lukem fname, lineno, 0 );
685 1.1 lukem rc = 1;
686 1.1 lukem goto private_destroy;
687 1.1 lukem }
688 1.1 lukem }
689 1.1 lukem }
690 1.1 lukem }
691 1.1 lukem
692 1.1 lukem return rc;
693 1.1 lukem }
694 1.1 lukem
695 1.1 lukem enum db_which {
696 1.1 lukem db_open = 0,
697 1.1 lukem db_close,
698 1.1 lukem db_destroy,
699 1.1 lukem
700 1.1 lukem db_last
701 1.1 lukem };
702 1.1 lukem
703 1.1 lukem typedef struct ldap_distproc_db_apply_t {
704 1.1 lukem BackendDB *be;
705 1.1 lukem BI_db_func *func;
706 1.1 lukem } ldap_distproc_db_apply_t;
707 1.1 lukem
708 1.1 lukem static int
709 1.1 lukem ldap_distproc_db_apply( void *datum, void *arg )
710 1.1 lukem {
711 1.1 lukem ldapinfo_t *li = (ldapinfo_t *)datum;
712 1.1 lukem ldap_distproc_db_apply_t *lca = (ldap_distproc_db_apply_t *)arg;
713 1.1 lukem
714 1.1 lukem lca->be->be_private = (void *)li;
715 1.1 lukem
716 1.1 lukem return lca->func( lca->be, NULL );
717 1.1 lukem }
718 1.1 lukem
719 1.1 lukem static int
720 1.1 lukem ldap_distproc_db_func(
721 1.1 lukem BackendDB *be,
722 1.1 lukem enum db_which which
723 1.1 lukem )
724 1.1 lukem {
725 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
726 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
727 1.1 lukem
728 1.1 lukem int rc = 0;
729 1.1 lukem
730 1.1 lukem if ( lc ) {
731 1.1 lukem BI_db_func *func = (&lback->bi_db_open)[ which ];
732 1.1 lukem
733 1.1 lukem if ( func != NULL && lc->lc_common_li != NULL ) {
734 1.1 lukem BackendDB db = *be;
735 1.1 lukem
736 1.1 lukem db.bd_info = lback;
737 1.1 lukem db.be_private = lc->lc_common_li;
738 1.1 lukem
739 1.1 lukem rc = func( &db, NULL );
740 1.1 lukem
741 1.1 lukem if ( rc != 0 ) {
742 1.1 lukem return rc;
743 1.1 lukem }
744 1.1 lukem
745 1.1 lukem if ( lc->lc_lai.lai_tree != NULL ) {
746 1.1 lukem ldap_distproc_db_apply_t lca;
747 1.1 lukem
748 1.1 lukem lca.be = &db;
749 1.1 lukem lca.func = func;
750 1.1 lukem
751 1.1 lukem rc = avl_apply( lc->lc_lai.lai_tree,
752 1.1 lukem ldap_distproc_db_apply, (void *)&lca,
753 1.1 lukem 1, AVL_INORDER ) != AVL_NOMORE;
754 1.1 lukem }
755 1.1 lukem }
756 1.1 lukem }
757 1.1 lukem
758 1.1 lukem return rc;
759 1.1 lukem }
760 1.1 lukem
761 1.1 lukem static int
762 1.1 lukem ldap_distproc_db_open(
763 1.1 lukem BackendDB *be,
764 1.1 lukem ConfigReply *cr )
765 1.1 lukem {
766 1.1 lukem return ldap_distproc_db_func( be, db_open );
767 1.1 lukem }
768 1.1 lukem
769 1.1 lukem static int
770 1.1 lukem ldap_distproc_db_close(
771 1.1 lukem BackendDB *be,
772 1.1 lukem ConfigReply *cr )
773 1.1 lukem {
774 1.1 lukem return ldap_distproc_db_func( be, db_close );
775 1.1 lukem }
776 1.1 lukem
777 1.1 lukem static int
778 1.1 lukem ldap_distproc_db_destroy(
779 1.1 lukem BackendDB *be,
780 1.1 lukem ConfigReply *cr )
781 1.1 lukem {
782 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
783 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
784 1.1 lukem
785 1.1 lukem int rc;
786 1.1 lukem
787 1.1 lukem rc = ldap_distproc_db_func( be, db_destroy );
788 1.1 lukem
789 1.1 lukem if ( lc ) {
790 1.1 lukem avl_free( lc->lc_lai.lai_tree, NULL );
791 1.1 lukem ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex );
792 1.1 lukem ch_free( lc );
793 1.1 lukem }
794 1.1 lukem
795 1.1 lukem return rc;
796 1.1 lukem }
797 1.1 lukem
798 1.1 lukem /*
799 1.1 lukem * inits one instance of the slapd-ldap backend, and stores
800 1.1 lukem * the private info in be_private of the arg
801 1.1 lukem */
802 1.1 lukem static int
803 1.1 lukem ldap_distproc_db_init_common(
804 1.1 lukem BackendDB *be )
805 1.1 lukem {
806 1.1 lukem BackendInfo *bi = be->bd_info;
807 1.1 lukem int t;
808 1.1 lukem
809 1.1 lukem be->bd_info = lback;
810 1.1 lukem be->be_private = NULL;
811 1.1 lukem t = lback->bi_db_init( be, NULL );
812 1.1 lukem if ( t != 0 ) {
813 1.1 lukem return t;
814 1.1 lukem }
815 1.1 lukem be->bd_info = bi;
816 1.1 lukem
817 1.1 lukem return 0;
818 1.1 lukem }
819 1.1 lukem
820 1.1 lukem /*
821 1.1 lukem * inits one instance of the slapd-ldap backend, stores
822 1.1 lukem * the private info in be_private of the arg and fills
823 1.1 lukem * selected fields with data from the template.
824 1.1 lukem *
825 1.1 lukem * NOTE: add checks about the other fields of the template,
826 1.1 lukem * which are ignored and SHOULD NOT be configured by the user.
827 1.1 lukem */
828 1.1 lukem static int
829 1.1 lukem ldap_distproc_db_init_one(
830 1.1 lukem BackendDB *be )
831 1.1 lukem {
832 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
833 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
834 1.1 lukem
835 1.1 lukem BackendInfo *bi = be->bd_info;
836 1.1 lukem ldapinfo_t *li;
837 1.1 lukem
838 1.1 lukem slap_op_t t;
839 1.1 lukem
840 1.1 lukem be->bd_info = lback;
841 1.1 lukem be->be_private = NULL;
842 1.1 lukem t = lback->bi_db_init( be, NULL );
843 1.1 lukem if ( t != 0 ) {
844 1.1 lukem return t;
845 1.1 lukem }
846 1.1 lukem li = (ldapinfo_t *)be->be_private;
847 1.1 lukem
848 1.1 lukem /* copy common data */
849 1.1 lukem li->li_nretries = lc->lc_common_li->li_nretries;
850 1.1 lukem li->li_flags = lc->lc_common_li->li_flags;
851 1.1 lukem li->li_version = lc->lc_common_li->li_version;
852 1.1 lukem for ( t = 0; t < SLAP_OP_LAST; t++ ) {
853 1.1 lukem li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ];
854 1.1 lukem }
855 1.1 lukem be->bd_info = bi;
856 1.1 lukem
857 1.1 lukem return 0;
858 1.1 lukem }
859 1.1 lukem
860 1.1 lukem typedef struct ldap_distproc_conn_apply_t {
861 1.1 lukem BackendDB *be;
862 1.1 lukem Connection *conn;
863 1.1 lukem } ldap_distproc_conn_apply_t;
864 1.1 lukem
865 1.1 lukem static int
866 1.1 lukem ldap_distproc_conn_apply( void *datum, void *arg )
867 1.1 lukem {
868 1.1 lukem ldapinfo_t *li = (ldapinfo_t *)datum;
869 1.1 lukem ldap_distproc_conn_apply_t *lca = (ldap_distproc_conn_apply_t *)arg;
870 1.1 lukem
871 1.1 lukem lca->be->be_private = (void *)li;
872 1.1 lukem
873 1.1 lukem return lback->bi_connection_destroy( lca->be, lca->conn );
874 1.1 lukem }
875 1.1 lukem
876 1.1 lukem static int
877 1.1 lukem ldap_distproc_connection_destroy(
878 1.1 lukem BackendDB *be,
879 1.1 lukem Connection *conn
880 1.1 lukem )
881 1.1 lukem {
882 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
883 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private;
884 1.1 lukem void *private = be->be_private;
885 1.1 lukem ldap_distproc_conn_apply_t lca;
886 1.1 lukem int rc;
887 1.1 lukem
888 1.1 lukem be->be_private = NULL;
889 1.1 lukem lca.be = be;
890 1.1 lukem lca.conn = conn;
891 1.1 lukem ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );
892 1.1 lukem rc = avl_apply( lc->lc_lai.lai_tree, ldap_distproc_conn_apply,
893 1.1 lukem (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE;
894 1.1 lukem ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );
895 1.1 lukem be->be_private = private;
896 1.1 lukem
897 1.1 lukem return rc;
898 1.1 lukem }
899 1.1 lukem
900 1.1 lukem static int
901 1.1 lukem ldap_distproc_parse_returnContRef_ctrl(
902 1.1 lukem Operation *op,
903 1.1 lukem SlapReply *rs,
904 1.1 lukem LDAPControl *ctrl )
905 1.1 lukem {
906 1.1 lukem if ( get_returnContRef( op ) != SLAP_CONTROL_NONE ) {
907 1.1 lukem rs->sr_text = "returnContinuationReference control specified multiple times";
908 1.1 lukem return LDAP_PROTOCOL_ERROR;
909 1.1 lukem }
910 1.1 lukem
911 1.1 lukem if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
912 1.1 lukem rs->sr_text = "returnContinuationReference control specified with pagedResults control";
913 1.1 lukem return LDAP_PROTOCOL_ERROR;
914 1.1 lukem }
915 1.1 lukem
916 1.1 lukem if ( !BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
917 1.1 lukem rs->sr_text = "returnContinuationReference control: value must be NULL";
918 1.1 lukem return LDAP_PROTOCOL_ERROR;
919 1.1 lukem }
920 1.1 lukem
921 1.1 lukem op->o_returnContRef = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL;
922 1.1 lukem
923 1.1 lukem return LDAP_SUCCESS;
924 1.1 lukem }
925 1.1 lukem
926 1.1 lukem static int
927 1.1 lukem ldap_exop_chained_request(
928 1.1 lukem Operation *op,
929 1.1 lukem SlapReply *rs )
930 1.1 lukem {
931 1.1 lukem Statslog( LDAP_DEBUG_STATS, "%s CHAINED REQUEST\n",
932 1.1 lukem op->o_log_prefix, 0, 0, 0, 0 );
933 1.1 lukem
934 1.1 lukem rs->sr_err = backend_check_restrictions( op, rs,
935 1.1 lukem (struct berval *)&slap_EXOP_CHAINEDREQUEST );
936 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
937 1.1 lukem return rs->sr_err;
938 1.1 lukem }
939 1.1 lukem
940 1.1 lukem /* by now, just reject requests */
941 1.1 lukem rs->sr_text = "under development";
942 1.1 lukem return LDAP_UNWILLING_TO_PERFORM;
943 1.1 lukem }
944 1.1 lukem
945 1.1 lukem
946 1.1 lukem static slap_overinst distproc;
947 1.1 lukem
948 1.1 lukem int
949 1.1 lukem distproc_initialize( void )
950 1.1 lukem {
951 1.1 lukem int rc;
952 1.1 lukem
953 1.1 lukem /* Make sure we don't exceed the bits reserved for userland */
954 1.1 lukem config_check_userland( DP_LAST );
955 1.1 lukem
956 1.1 lukem rc = load_extop( (struct berval *)&slap_EXOP_CHAINEDREQUEST,
957 1.1 lukem SLAP_EXOP_HIDE, ldap_exop_chained_request );
958 1.1 lukem if ( rc != LDAP_SUCCESS ) {
959 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
960 1.1 lukem "unable to register chainedRequest exop: %d.\n",
961 1.1 lukem rc, 0, 0 );
962 1.1 lukem return rc;
963 1.1 lukem }
964 1.1 lukem
965 1.1 lukem #ifdef LDAP_DEVEL
966 1.1 lukem rc = supported_feature_load( &slap_FEATURE_CANCHAINOPS );
967 1.1 lukem if ( rc != LDAP_SUCCESS ) {
968 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
969 1.1 lukem "unable to register canChainOperations supported feature: %d.\n",
970 1.1 lukem rc, 0, 0 );
971 1.1 lukem return rc;
972 1.1 lukem }
973 1.1 lukem #endif
974 1.1 lukem
975 1.1 lukem rc = register_supported_control( LDAP_CONTROL_X_RETURNCONTREF,
976 1.1 lukem SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL,
977 1.1 lukem ldap_distproc_parse_returnContRef_ctrl, &sc_returnContRef );
978 1.1 lukem if ( rc != LDAP_SUCCESS ) {
979 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: "
980 1.1 lukem "unable to register returnContinuationReference control: %d.\n",
981 1.1 lukem rc, 0, 0 );
982 1.1 lukem return rc;
983 1.1 lukem }
984 1.1 lukem
985 1.1 lukem distproc.on_bi.bi_type = "distproc";
986 1.1 lukem distproc.on_bi.bi_db_init = ldap_distproc_db_init;
987 1.1 lukem distproc.on_bi.bi_db_config = ldap_distproc_db_config;
988 1.1 lukem distproc.on_bi.bi_db_open = ldap_distproc_db_open;
989 1.1 lukem distproc.on_bi.bi_db_close = ldap_distproc_db_close;
990 1.1 lukem distproc.on_bi.bi_db_destroy = ldap_distproc_db_destroy;
991 1.1 lukem
992 1.1 lukem /* ... otherwise the underlying backend's function would be called,
993 1.1 lukem * likely passing an invalid entry; on the contrary, the requested
994 1.1 lukem * operational attributes should have been returned while chasing
995 1.1 lukem * the referrals. This all in all is a bit messy, because part
996 1.1 lukem * of the operational attributes are generated by the backend;
997 1.1 lukem * part by the frontend; back-ldap should receive all the available
998 1.1 lukem * ones from the remote server, but then, on its own, it strips those
999 1.1 lukem * it assumes will be (re)generated by the frontend (e.g.
1000 1.1 lukem * subschemaSubentry, entryDN, ...) */
1001 1.1 lukem distproc.on_bi.bi_operational = ldap_distproc_operational;
1002 1.1 lukem
1003 1.1 lukem distproc.on_bi.bi_connection_destroy = ldap_distproc_connection_destroy;
1004 1.1 lukem
1005 1.1 lukem distproc.on_response = ldap_distproc_response;
1006 1.1 lukem
1007 1.1 lukem distproc.on_bi.bi_cf_ocs = distproc_ocs;
1008 1.1 lukem
1009 1.1 lukem rc = config_register_schema( distproc_cfg, distproc_ocs );
1010 1.1 lukem if ( rc ) {
1011 1.1 lukem return rc;
1012 1.1 lukem }
1013 1.1 lukem
1014 1.1 lukem return overlay_register( &distproc );
1015 1.1 lukem }
1016 1.1 lukem
1017 1.1 lukem #endif /* SLAP_DISTPROC */
1018