1 /* distproc.c - implement distributed procedures */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/distproc.c,v 1.3.2.7 2008/02/12 00:58:15 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2005-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2003 Howard Chu.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by Pierangelo Masarati for inclusion
19 * in OpenLDAP Software.
20 * Based on back-ldap and slapo-chain, developed by Howard Chu
27 #include <ac/string.h>
28 #include <ac/socket.h>
34 #include "back-ldap.h"
39 * From <draft-sermersheim-ldap-distproc>
42 ContinuationReference ::= SET {
43 referralURI [0] SET SIZE (1..MAX) OF URI,
44 localReference [2] LDAPDN,
45 referenceType [3] ReferenceType,
46 remainingName [4] RelativeLDAPDN OPTIONAL,
47 searchScope [5] SearchScope OPTIONAL,
48 searchedSubtrees [6] SearchedSubtrees OPTIONAL,
49 failedName [7] LDAPDN OPTIONAL,
52 ReferenceType ::= ENUMERATED {
56 nonSpecificSubordinate (3),
59 immediateSuperior (6),
63 SearchScope ::= ENUMERATED {
67 subordinateSubtree (3),
70 SearchedSubtrees ::= SET OF RelativeLDAPDN
72 LDAPDN, RelativeLDAPDN, and LDAPString, are defined in [RFC2251].
76 typedef enum ReferenceType_t
{
77 LDAP_DP_RT_UNKNOWN
= -1,
78 LDAP_DP_RT_SUPERIOR
= 0,
79 LDAP_DP_RT_SUBORDINATE
= 1,
81 LDAP_DP_RT_NONSPECIFICSUBORDINATE
= 3,
82 LDAP_DP_RT_SUPPLIER
= 4,
83 LDAP_DP_RT_MASTER
= 5,
84 LDAP_DP_RT_IMMEDIATESUPERIOR
= 6,
89 typedef enum SearchScope_t
{
90 LDAP_DP_SS_UNKNOWN
= -1,
91 LDAP_DP_SS_BASEOBJECT
= 0,
92 LDAP_DP_SS_SINGLELEVEL
= 1,
93 LDAP_DP_SS_WHOLESUBTREE
= 2,
94 LDAP_DP_SS_SUBORDINATESUBTREE
= 3,
98 typedef struct ContinuationReference_t
{
99 BerVarray cr_referralURI
;
101 struct berval cr_localReference
;
102 ReferenceType_t cr_referenceType
;
103 struct berval cr_remainingName
;
104 SearchScope_t cr_searchScope
;
105 BerVarray cr_searchedSubtrees
;
106 struct berval cr_failedName
;
107 } ContinuationReference_t
;
108 #define CR_INIT { NULL, BER_BVNULL, LDAP_DP_RT_UNKNOWN, BER_BVNULL, LDAP_DP_SS_UNKNOWN, NULL, BER_BVNULL }
110 static struct berval bv2rt
[] = {
111 BER_BVC( "superior" ),
112 BER_BVC( "subordinate" ),
114 BER_BVC( "nonSpecificSubordinate" ),
115 BER_BVC( "supplier" ),
117 BER_BVC( "immediateSuperior" ),
122 static struct berval bv2ss
[] = {
123 BER_BVC( "baseObject" ),
124 BER_BVC( "singleLevel" ),
125 BER_BVC( "wholeSubtree" ),
126 BER_BVC( "subordinateSubtree" ),
130 static struct berval
*
131 ldap_distproc_rt2bv( ReferenceType_t rt
)
137 ldap_distproc_rt2str( ReferenceType_t rt
)
139 return bv2rt
[ rt
].bv_val
;
142 static ReferenceType_t
143 ldap_distproc_bv2rt( struct berval
*bv
)
147 for ( rt
= 0; !BER_BVISNULL( &bv2rt
[ rt
] ); rt
++ ) {
148 if ( ber_bvstrcasecmp( bv
, &bv2rt
[ rt
] ) == 0 ) {
153 return LDAP_DP_RT_UNKNOWN
;
156 static ReferenceType_t
157 ldap_distproc_str2rt( const char *s
)
161 ber_str2bv( s
, 0, 0, &bv
);
162 return ldap_distproc_bv2rt( &bv
);
165 static struct berval
*
166 ldap_distproc_ss2bv( SearchScope_t ss
)
172 ldap_distproc_ss2str( SearchScope_t ss
)
174 return bv2ss
[ ss
].bv_val
;
178 ldap_distproc_bv2ss( struct berval
*bv
)
182 for ( ss
= 0; !BER_BVISNULL( &bv2ss
[ ss
] ); ss
++ ) {
183 if ( ber_bvstrcasecmp( bv
, &bv2ss
[ ss
] ) == 0 ) {
188 return LDAP_DP_SS_UNKNOWN
;
192 ldap_distproc_str2ss( const char *s
)
196 ber_str2bv( s
, 0, 0, &bv
);
197 return ldap_distproc_bv2ss( &bv
);
201 * NOTE: this overlay assumes that the chainingBehavior control
202 * is registered by the chain overlay; it may move here some time.
203 * This overlay provides support for that control as well.
207 static int sc_returnContRef
;
208 #define o_returnContRef o_ctrlflag[sc_returnContRef]
209 #define get_returnContRef(op) ((op)->o_returnContRef & SLAP_CONTROL_MASK)
211 static struct berval slap_EXOP_CHAINEDREQUEST
= BER_BVC( LDAP_EXOP_X_CHAINEDREQUEST
);
212 static struct berval slap_FEATURE_CANCHAINOPS
= BER_BVC( LDAP_FEATURE_X_CANCHAINOPS
);
214 static BackendInfo
*lback
;
216 typedef struct ldap_distproc_t
{
217 /* "common" configuration info (anything occurring before an "uri") */
218 ldapinfo_t
*lc_common_li
;
220 /* current configuration info */
221 ldapinfo_t
*lc_cfg_li
;
223 /* tree of configured[/generated?] "uri" info */
224 ldap_avl_info_t lc_lai
;
227 #define LDAP_DISTPROC_F_NONE (0x00U)
228 #define LDAP_DISTPROC_F_CHAINING (0x01U)
229 #define LDAP_DISTPROC_F_CACHE_URI (0x10U)
231 #define LDAP_DISTPROC_CHAINING( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CHAINING ) == LDAP_DISTPROC_F_CHAINING )
232 #define LDAP_DISTPROC_CACHE_URI( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CACHE_URI ) == LDAP_DISTPROC_F_CACHE_URI )
236 static int ldap_distproc_db_init_common( BackendDB
*be
);
237 static int ldap_distproc_db_init_one( BackendDB
*be
);
238 #define ldap_distproc_db_open_one(be) (lback)->bi_db_open( (be) )
239 #define ldap_distproc_db_close_one(be) (0)
240 #define ldap_distproc_db_destroy_one(be, ca) (lback)->bi_db_destroy( (be), (ca) )
243 ldap_distproc_parse_ctrl(
249 ldap_distproc_uri_cmp( const void *c1
, const void *c2
)
251 const ldapinfo_t
*li1
= (const ldapinfo_t
*)c1
;
252 const ldapinfo_t
*li2
= (const ldapinfo_t
*)c2
;
254 assert( li1
->li_bvuri
!= NULL
);
255 assert( !BER_BVISNULL( &li1
->li_bvuri
[ 0 ] ) );
256 assert( BER_BVISNULL( &li1
->li_bvuri
[ 1 ] ) );
258 assert( li2
->li_bvuri
!= NULL
);
259 assert( !BER_BVISNULL( &li2
->li_bvuri
[ 0 ] ) );
260 assert( BER_BVISNULL( &li2
->li_bvuri
[ 1 ] ) );
262 /* If local DNs don't match, it is definitely not a match */
263 return ber_bvcmp( &li1
->li_bvuri
[ 0 ], &li2
->li_bvuri
[ 0 ] );
267 ldap_distproc_uri_dup( void *c1
, void *c2
)
269 ldapinfo_t
*li1
= (ldapinfo_t
*)c1
;
270 ldapinfo_t
*li2
= (ldapinfo_t
*)c2
;
272 assert( li1
->li_bvuri
!= NULL
);
273 assert( !BER_BVISNULL( &li1
->li_bvuri
[ 0 ] ) );
274 assert( BER_BVISNULL( &li1
->li_bvuri
[ 1 ] ) );
276 assert( li2
->li_bvuri
!= NULL
);
277 assert( !BER_BVISNULL( &li2
->li_bvuri
[ 0 ] ) );
278 assert( BER_BVISNULL( &li2
->li_bvuri
[ 1 ] ) );
280 /* Cannot have more than one shared session with same DN */
281 if ( ber_bvcmp( &li1
->li_bvuri
[ 0 ], &li2
->li_bvuri
[ 0 ] ) == 0 ) {
289 ldap_distproc_operational( Operation
*op
, SlapReply
*rs
)
291 /* Trap entries generated by back-ldap.
293 * FIXME: we need a better way to recognize them; a cleaner
294 * solution would be to be able to intercept the response
295 * of be_operational(), so that we can divert only those
296 * calls that fail because operational attributes were
297 * requested for entries that do not belong to the underlying
298 * database. This fix is likely to intercept also entries
299 * generated by back-perl and so. */
300 if ( rs
->sr_entry
->e_private
== NULL
) {
304 return SLAP_CB_CONTINUE
;
308 ldap_distproc_response( Operation
*op
, SlapReply
*rs
)
310 return SLAP_CB_CONTINUE
;
318 /* NOTE: the chaining behavior control is registered
319 * by the chain overlay; it may move here some time */
326 static ConfigDriver distproc_cfgen
;
327 static ConfigCfAdd distproc_cfadd
;
328 static ConfigLDAPadd distproc_ldadd
;
330 static ConfigTable distproc_cfg
[] = {
331 { "distproc-chaining", "args",
332 2, 4, 0, ARG_MAGIC
|ARG_BERVAL
|DP_CHAINING
, distproc_cfgen
,
333 /* NOTE: using the same attributeTypes defined
334 * for the "chain" overlay */
335 "( OLcfgOvAt:3.1 NAME 'olcChainingBehavior' "
336 "DESC 'Chaining behavior control parameters (draft-sermersheim-ldap-chaining)' "
337 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
338 { "distproc-cache-uri", "TRUE/FALSE",
339 2, 2, 0, ARG_MAGIC
|ARG_ON_OFF
|DP_CACHE_URI
, distproc_cfgen
,
340 "( OLcfgOvAt:3.2 NAME 'olcChainCacheURI' "
341 "DESC 'Enables caching of URIs not present in configuration' "
343 "SINGLE-VALUE )", NULL
, NULL
},
344 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
}
347 static ConfigOCs distproc_ocs
[] = {
349 "NAME 'olcDistProcConfig' "
350 "DESC 'Distributed procedures <draft-sermersheim-ldap-distproc> configuration' "
351 "SUP olcOverlayConfig "
353 "olcChainingBehavior $ "
356 Cft_Overlay
, distproc_cfg
, NULL
, distproc_cfadd
},
358 "NAME 'olcDistProcDatabase' "
359 "DESC 'Distributed procedure remote server configuration' "
361 Cft_Misc
, distproc_cfg
, distproc_ldadd
},
366 distproc_ldadd( CfEntryInfo
*p
, Entry
*e
, ConfigArgs
*ca
)
373 AttributeDescription
*ad
= NULL
;
379 if ( p
->ce_type
!= Cft_Overlay
381 || p
->ce_bi
->bi_cf_ocs
!= distproc_ocs
)
383 return LDAP_CONSTRAINT_VIOLATION
;
386 on
= (slap_overinst
*)p
->ce_bi
;
387 lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
389 assert( ca
->be
== NULL
);
390 ca
->be
= (BackendDB
*)ch_calloc( 1, sizeof( BackendDB
) );
392 ca
->be
->bd_info
= (BackendInfo
*)on
;
394 rc
= slap_str2ad( "olcDbURI", &ad
, &text
);
395 assert( rc
== LDAP_SUCCESS
);
397 at
= attr_find( e
->e_attrs
, ad
);
398 if ( lc
->lc_common_li
== NULL
&& at
!= NULL
) {
399 /* FIXME: we should generate an empty default entry
400 * if none is supplied */
401 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
402 "first underlying database \"%s\" "
403 "cannot contain attribute \"%s\".\n",
404 e
->e_name
.bv_val
, ad
->ad_cname
.bv_val
, 0 );
405 rc
= LDAP_CONSTRAINT_VIOLATION
;
408 } else if ( lc
->lc_common_li
!= NULL
&& at
== NULL
) {
409 /* FIXME: we should generate an empty default entry
410 * if none is supplied */
411 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
412 "subsequent underlying database \"%s\" "
413 "must contain attribute \"%s\".\n",
414 e
->e_name
.bv_val
, ad
->ad_cname
.bv_val
, 0 );
415 rc
= LDAP_CONSTRAINT_VIOLATION
;
419 if ( lc
->lc_common_li
== NULL
) {
420 rc
= ldap_distproc_db_init_common( ca
->be
);
423 rc
= ldap_distproc_db_init_one( ca
->be
);
427 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
428 "unable to init %sunderlying database \"%s\".\n",
429 lc
->lc_common_li
== NULL
? "common " : "", e
->e_name
.bv_val
, 0 );
430 return LDAP_CONSTRAINT_VIOLATION
;
433 li
= ca
->be
->be_private
;
435 if ( lc
->lc_common_li
== NULL
) {
436 lc
->lc_common_li
= li
;
438 } else if ( avl_insert( &lc
->lc_lai
.lai_tree
, (caddr_t
)li
,
439 ldap_distproc_uri_cmp
, ldap_distproc_uri_dup
) )
441 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
442 "database \"%s\" insert failed.\n",
443 e
->e_name
.bv_val
, 0, 0 );
444 rc
= LDAP_CONSTRAINT_VIOLATION
;
449 if ( rc
!= LDAP_SUCCESS
) {
450 (void)ldap_distproc_db_destroy_one( ca
->be
, NULL
);
458 typedef struct ldap_distproc_cfadd_apply_t
{
464 } ldap_distproc_cfadd_apply_t
;
467 ldap_distproc_cfadd_apply( void *datum
, void *arg
)
469 ldapinfo_t
*li
= (ldapinfo_t
*)datum
;
470 ldap_distproc_cfadd_apply_t
*lca
= (ldap_distproc_cfadd_apply_t
*)arg
;
474 /* FIXME: should not hardcode "olcDatabase" here */
475 bv
.bv_len
= snprintf( lca
->ca
->cr_msg
, sizeof( lca
->ca
->cr_msg
),
476 "olcDatabase={%d}%s", lca
->count
, lback
->bi_type
);
477 bv
.bv_val
= lca
->ca
->cr_msg
;
479 lca
->ca
->be
->be_private
= (void *)li
;
480 config_build_entry( lca
->op
, lca
->rs
, lca
->p
->e_private
, lca
->ca
,
481 &bv
, lback
->bi_cf_ocs
, &distproc_ocs
[ 1 ] );
489 distproc_cfadd( Operation
*op
, SlapReply
*rs
, Entry
*p
, ConfigArgs
*ca
)
491 CfEntryInfo
*pe
= p
->e_private
;
492 slap_overinst
*on
= (slap_overinst
*)pe
->ce_bi
;
493 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
494 void *priv
= (void *)ca
->be
->be_private
;
496 if ( lback
->bi_cf_ocs
) {
497 ldap_distproc_cfadd_apply_t lca
= { 0 };
505 (void)ldap_distproc_cfadd_apply( (void *)lc
->lc_common_li
, (void *)&lca
);
507 (void)avl_apply( lc
->lc_lai
.lai_tree
, ldap_distproc_cfadd_apply
,
508 &lca
, 1, AVL_INORDER
);
510 ca
->be
->be_private
= priv
;
517 distproc_cfgen( ConfigArgs
*c
)
519 slap_overinst
*on
= (slap_overinst
*)c
->bi
;
520 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
524 if ( c
->op
== SLAP_CONFIG_EMIT
) {
527 c
->value_int
= LDAP_DISTPROC_CACHE_URI( lc
);
536 } else if ( c
->op
== LDAP_MOD_DELETE
) {
542 lc
->lc_flags
&= ~LDAP_DISTPROC_F_CACHE_URI
;
553 if ( c
->value_int
) {
554 lc
->lc_flags
|= LDAP_DISTPROC_F_CACHE_URI
;
556 lc
->lc_flags
&= ~LDAP_DISTPROC_F_CACHE_URI
;
569 ldap_distproc_db_init(
573 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
574 ldap_distproc_t
*lc
= NULL
;
576 if ( lback
== NULL
) {
577 lback
= backend_info( "ldap" );
579 if ( lback
== NULL
) {
584 lc
= ch_malloc( sizeof( ldap_distproc_t
) );
588 memset( lc
, 0, sizeof( ldap_distproc_t
) );
589 ldap_pvt_thread_mutex_init( &lc
->lc_lai
.lai_mutex
);
591 on
->on_bi
.bi_private
= (void *)lc
;
597 ldap_distproc_db_config(
604 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
605 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
607 int rc
= SLAP_CONF_UNKNOWN
;
609 if ( lc
->lc_common_li
== NULL
) {
610 void *be_private
= be
->be_private
;
611 ldap_distproc_db_init_common( be
);
612 lc
->lc_common_li
= lc
->lc_cfg_li
= (ldapinfo_t
*)be
->be_private
;
613 be
->be_private
= be_private
;
616 /* Something for the distproc database? */
617 if ( strncasecmp( argv
[ 0 ], "distproc-", STRLENOF( "distproc-" ) ) == 0 ) {
618 char *save_argv0
= argv
[ 0 ];
619 BackendInfo
*bd_info
= be
->bd_info
;
620 void *be_private
= be
->be_private
;
621 ConfigOCs
*be_cf_ocs
= be
->be_cf_ocs
;
624 argv
[ 0 ] += STRLENOF( "distproc-" );
626 if ( strcasecmp( argv
[ 0 ], "uri" ) == 0 ) {
627 rc
= ldap_distproc_db_init_one( be
);
629 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
630 "underlying slapd-ldap initialization failed.\n.",
634 lc
->lc_cfg_li
= be
->be_private
;
638 /* TODO: add checks on what other slapd-ldap(5) args
639 * should be put in the template; this is not quite
640 * harmful, because attributes that shouldn't don't
641 * get actually used, but the user should at least
646 be
->be_private
= (void *)lc
->lc_cfg_li
;
647 be
->be_cf_ocs
= lback
->bi_cf_ocs
;
649 rc
= config_generic_wrapper( be
, fname
, lineno
, argc
, argv
);
651 argv
[ 0 ] = save_argv0
;
652 be
->be_cf_ocs
= be_cf_ocs
;
653 be
->be_private
= be_private
;
654 be
->bd_info
= bd_info
;
662 db
.be_private
= (void *)lc
->lc_cfg_li
;
663 ldap_distproc_db_destroy_one( &db
, NULL
);
664 lc
->lc_cfg_li
= NULL
;
667 if ( lc
->lc_cfg_li
->li_bvuri
== NULL
668 || BER_BVISNULL( &lc
->lc_cfg_li
->li_bvuri
[ 0 ] )
669 || !BER_BVISNULL( &lc
->lc_cfg_li
->li_bvuri
[ 1 ] ) )
671 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
672 "no URI list allowed in slapo-distproc.\n",
675 goto private_destroy
;
678 if ( avl_insert( &lc
->lc_lai
.lai_tree
,
679 (caddr_t
)lc
->lc_cfg_li
,
680 ldap_distproc_uri_cmp
, ldap_distproc_uri_dup
) )
682 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
683 "duplicate URI in slapo-distproc.\n",
686 goto private_destroy
;
703 typedef struct ldap_distproc_db_apply_t
{
706 } ldap_distproc_db_apply_t
;
709 ldap_distproc_db_apply( void *datum
, void *arg
)
711 ldapinfo_t
*li
= (ldapinfo_t
*)datum
;
712 ldap_distproc_db_apply_t
*lca
= (ldap_distproc_db_apply_t
*)arg
;
714 lca
->be
->be_private
= (void *)li
;
716 return lca
->func( lca
->be
, NULL
);
720 ldap_distproc_db_func(
725 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
726 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
731 BI_db_func
*func
= (&lback
->bi_db_open
)[ which
];
733 if ( func
!= NULL
&& lc
->lc_common_li
!= NULL
) {
737 db
.be_private
= lc
->lc_common_li
;
739 rc
= func( &db
, NULL
);
745 if ( lc
->lc_lai
.lai_tree
!= NULL
) {
746 ldap_distproc_db_apply_t lca
;
751 rc
= avl_apply( lc
->lc_lai
.lai_tree
,
752 ldap_distproc_db_apply
, (void *)&lca
,
753 1, AVL_INORDER
) != AVL_NOMORE
;
762 ldap_distproc_db_open(
766 return ldap_distproc_db_func( be
, db_open
);
770 ldap_distproc_db_close(
774 return ldap_distproc_db_func( be
, db_close
);
778 ldap_distproc_db_destroy(
782 slap_overinst
*on
= (slap_overinst
*) be
->bd_info
;
783 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
787 rc
= ldap_distproc_db_func( be
, db_destroy
);
790 avl_free( lc
->lc_lai
.lai_tree
, NULL
);
791 ldap_pvt_thread_mutex_destroy( &lc
->lc_lai
.lai_mutex
);
799 * inits one instance of the slapd-ldap backend, and stores
800 * the private info in be_private of the arg
803 ldap_distproc_db_init_common(
806 BackendInfo
*bi
= be
->bd_info
;
810 be
->be_private
= NULL
;
811 t
= lback
->bi_db_init( be
, NULL
);
821 * inits one instance of the slapd-ldap backend, stores
822 * the private info in be_private of the arg and fills
823 * selected fields with data from the template.
825 * NOTE: add checks about the other fields of the template,
826 * which are ignored and SHOULD NOT be configured by the user.
829 ldap_distproc_db_init_one(
832 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
833 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
835 BackendInfo
*bi
= be
->bd_info
;
841 be
->be_private
= NULL
;
842 t
= lback
->bi_db_init( be
, NULL
);
846 li
= (ldapinfo_t
*)be
->be_private
;
848 /* copy common data */
849 li
->li_nretries
= lc
->lc_common_li
->li_nretries
;
850 li
->li_flags
= lc
->lc_common_li
->li_flags
;
851 li
->li_version
= lc
->lc_common_li
->li_version
;
852 for ( t
= 0; t
< SLAP_OP_LAST
; t
++ ) {
853 li
->li_timeout
[ t
] = lc
->lc_common_li
->li_timeout
[ t
];
860 typedef struct ldap_distproc_conn_apply_t
{
863 } ldap_distproc_conn_apply_t
;
866 ldap_distproc_conn_apply( void *datum
, void *arg
)
868 ldapinfo_t
*li
= (ldapinfo_t
*)datum
;
869 ldap_distproc_conn_apply_t
*lca
= (ldap_distproc_conn_apply_t
*)arg
;
871 lca
->be
->be_private
= (void *)li
;
873 return lback
->bi_connection_destroy( lca
->be
, lca
->conn
);
877 ldap_distproc_connection_destroy(
882 slap_overinst
*on
= (slap_overinst
*) be
->bd_info
;
883 ldap_distproc_t
*lc
= (ldap_distproc_t
*)on
->on_bi
.bi_private
;
884 void *private = be
->be_private
;
885 ldap_distproc_conn_apply_t lca
;
888 be
->be_private
= NULL
;
891 ldap_pvt_thread_mutex_lock( &lc
->lc_lai
.lai_mutex
);
892 rc
= avl_apply( lc
->lc_lai
.lai_tree
, ldap_distproc_conn_apply
,
893 (void *)&lca
, 1, AVL_INORDER
) != AVL_NOMORE
;
894 ldap_pvt_thread_mutex_unlock( &lc
->lc_lai
.lai_mutex
);
895 be
->be_private
= private;
901 ldap_distproc_parse_returnContRef_ctrl(
906 if ( get_returnContRef( op
) != SLAP_CONTROL_NONE
) {
907 rs
->sr_text
= "returnContinuationReference control specified multiple times";
908 return LDAP_PROTOCOL_ERROR
;
911 if ( op
->o_pagedresults
!= SLAP_CONTROL_NONE
) {
912 rs
->sr_text
= "returnContinuationReference control specified with pagedResults control";
913 return LDAP_PROTOCOL_ERROR
;
916 if ( !BER_BVISEMPTY( &ctrl
->ldctl_value
) ) {
917 rs
->sr_text
= "returnContinuationReference control: value must be NULL";
918 return LDAP_PROTOCOL_ERROR
;
921 op
->o_returnContRef
= ctrl
->ldctl_iscritical
? SLAP_CONTROL_CRITICAL
: SLAP_CONTROL_NONCRITICAL
;
927 ldap_exop_chained_request(
931 Statslog( LDAP_DEBUG_STATS
, "%s CHAINED REQUEST\n",
932 op
->o_log_prefix
, 0, 0, 0, 0 );
934 rs
->sr_err
= backend_check_restrictions( op
, rs
,
935 (struct berval
*)&slap_EXOP_CHAINEDREQUEST
);
936 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
940 /* by now, just reject requests */
941 rs
->sr_text
= "under development";
942 return LDAP_UNWILLING_TO_PERFORM
;
946 static slap_overinst distproc
;
949 distproc_initialize( void )
953 /* Make sure we don't exceed the bits reserved for userland */
954 config_check_userland( DP_LAST
);
956 rc
= load_extop( (struct berval
*)&slap_EXOP_CHAINEDREQUEST
,
957 SLAP_EXOP_HIDE
, ldap_exop_chained_request
);
958 if ( rc
!= LDAP_SUCCESS
) {
959 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
960 "unable to register chainedRequest exop: %d.\n",
966 rc
= supported_feature_load( &slap_FEATURE_CANCHAINOPS
);
967 if ( rc
!= LDAP_SUCCESS
) {
968 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
969 "unable to register canChainOperations supported feature: %d.\n",
975 rc
= register_supported_control( LDAP_CONTROL_X_RETURNCONTREF
,
976 SLAP_CTRL_GLOBAL
|SLAP_CTRL_ACCESS
|SLAP_CTRL_HIDE
, NULL
,
977 ldap_distproc_parse_returnContRef_ctrl
, &sc_returnContRef
);
978 if ( rc
!= LDAP_SUCCESS
) {
979 Debug( LDAP_DEBUG_ANY
, "slapd-distproc: "
980 "unable to register returnContinuationReference control: %d.\n",
985 distproc
.on_bi
.bi_type
= "distproc";
986 distproc
.on_bi
.bi_db_init
= ldap_distproc_db_init
;
987 distproc
.on_bi
.bi_db_config
= ldap_distproc_db_config
;
988 distproc
.on_bi
.bi_db_open
= ldap_distproc_db_open
;
989 distproc
.on_bi
.bi_db_close
= ldap_distproc_db_close
;
990 distproc
.on_bi
.bi_db_destroy
= ldap_distproc_db_destroy
;
992 /* ... otherwise the underlying backend's function would be called,
993 * likely passing an invalid entry; on the contrary, the requested
994 * operational attributes should have been returned while chasing
995 * the referrals. This all in all is a bit messy, because part
996 * of the operational attributes are generated by the backend;
997 * part by the frontend; back-ldap should receive all the available
998 * ones from the remote server, but then, on its own, it strips those
999 * it assumes will be (re)generated by the frontend (e.g.
1000 * subschemaSubentry, entryDN, ...) */
1001 distproc
.on_bi
.bi_operational
= ldap_distproc_operational
;
1003 distproc
.on_bi
.bi_connection_destroy
= ldap_distproc_connection_destroy
;
1005 distproc
.on_response
= ldap_distproc_response
;
1007 distproc
.on_bi
.bi_cf_ocs
= distproc_ocs
;
1009 rc
= config_register_schema( distproc_cfg
, distproc_ocs
);
1014 return overlay_register( &distproc
);
1017 #endif /* SLAP_DISTPROC */