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