2 * Copyright 1998-2001 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5 * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
7 * This work has been developed to fulfill the requirements
8 * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
9 * to the OpenLDAP Foundation in the hope that it may be useful
10 * to the Open Source community, but WITHOUT ANY WARRANTY.
12 * Permission is granted to anyone to use this software for any purpose
13 * on any computer system, and to alter it and redistribute it, subject
14 * to the following restrictions:
16 * 1. The author and SysNet s.n.c. are not responsible for the consequences
17 * of use of this software, no matter how awful, even if they arise from
20 * 2. The origin of this software must not be misrepresented, either by
21 * explicit claim or by omission. Since few users ever read sources,
22 * credits should appear in the documentation.
24 * 3. Altered versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software. Since few users
26 * ever read sources, credits should appear in the documentation.
27 * SysNet s.n.c. cannot be responsible for the consequences of the
30 * 4. This notice may not be removed or altered.
33 * This software is based on the backend back-ldap, implemented
34 * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
35 * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
36 * contributors. The contribution of the original software to the present
37 * implementation is acknowledged in this copyright statement.
39 * A special acknowledgement goes to Howard for the overall architecture
40 * (and for borrowing large pieces of code), and to Mark, who implemented
41 * from scratch the attribute/objectclass mapping.
43 * The original copyright statement follows.
45 * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
47 * Permission is granted to anyone to use this software for any purpose
48 * on any computer system, and to alter it and redistribute it, subject
49 * to the following restrictions:
51 * 1. The author is not responsible for the consequences of use of this
52 * software, no matter how awful, even if they arise from flaws in it.
54 * 2. The origin of this software must not be misrepresented, either by
55 * explicit claim or by omission. Since few users ever read sources,
56 * credits should appear in the documentation.
58 * 3. Altered versions must be plainly marked as such, and must not be
59 * misrepresented as being the original software. Since few users
60 * ever read sources, credits should appear in the
63 * 4. This notice may not be removed or altered.
72 #include "../back-ldap/back-ldap.h"
73 #include "back-meta.h"
76 * The meta-directory has one suffix, called <suffix>.
77 * It handles a pool of target servers, each with a branch suffix
78 * of the form <branch X>,<suffix>
80 * When the meta-directory receives a request with a dn that belongs
81 * to a branch, the corresponding target is invoked. When the dn
82 * does not belong to a specific branch, all the targets that
83 * are compatible with the dn are selected as candidates, and
84 * the request is spawned to all the candidate targets
86 * A request is characterized by a dn. The following cases are handled:
87 * - the dn is the suffix: <dn> == <suffix>,
88 * all the targets are candidates (search ...)
89 * - the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
90 * - the dn is a subtree of a branch suffix:
91 * <dn> == <rdn>,<branch X>,<suffix>,
92 * the target is the only candidate.
94 * A possible extension will include the handling of multiple suffixes
98 * returns 1 if suffix is candidate for dn, otherwise 0
100 * Note: this function should never be called if dn is the <suffix>.
103 meta_back_is_candidate(
109 int len = strlen( nsuffix );
111 if ( len > ndnlen ) {
113 * suffix longer than dn
115 if ( ! DN_SEPARATOR( nsuffix[ ( len - ndnlen ) - 1 ] ) ) {
117 * not a separator begins the possible common part
119 return META_NOT_CANDIDATE;
122 if ( strcmp( &nsuffix[ len - ndnlen ] , ndn ) == 0 ) {
126 return META_CANDIDATE;
130 if ( len < ndnlen && ! DN_SEPARATOR( ndn[ ( ndnlen - len ) - 1 ] ) ) {
132 * not a separator begins the possible common part
134 return META_NOT_CANDIDATE;
137 if ( strcmp( nsuffix, &ndn[ ndnlen - len ] ) == 0 ) {
141 return META_CANDIDATE;
144 return META_NOT_CANDIDATE;
148 * meta_back_count_candidates
150 * returns a count of the possible candidate targets
151 * Note: dn MUST be normalized
155 meta_back_count_candidates(
160 int i, cnt = 0, ndnlen = strlen( ndn );
163 * I know assertions should not check run-time values;
164 * at present I didn't find a place for such checks
167 assert( li->targets != NULL );
168 assert( li->ntargets != 0 );
170 for ( i = 0; i < li->ntargets; ++i ) {
171 if ( meta_back_is_candidate( li->targets[ i ]->suffix,
181 * meta_back_is_candidate_unique
183 * checks whether a candidate is unique
184 * Note: dn MUST be normalized
187 meta_back_is_candidate_unique(
192 return ( meta_back_count_candidates( li, ndn ) == 1 );
196 * meta_back_select_unique_candidate
198 * returns the index of the candidate in case it is unique, otherwise -1
199 * Note: dn MUST be normalized.
200 * Note: if defined, the default candidate is returned in case of no match.
203 meta_back_select_unique_candidate(
210 switch ( meta_back_count_candidates( li, ndn ) ) {
215 return ( li->defaulttarget == META_DEFAULT_TARGET_NONE
216 ? -1 : li->defaulttarget );
219 ndnlen = strlen( ndn );
220 for ( i = 0; i < li->ntargets; ++i ) {
221 if ( meta_back_is_candidate( li->targets[ i ]->suffix,
231 * meta_clear_unused_candidates
233 * clears all candidates except candidate
236 meta_clear_unused_candidates(
245 for ( i = 0; i < li->ntargets; ++i ) {
246 if ( i == candidate ) {
249 meta_clear_one_candidate( lc->conns[ i ], reallyclean );
256 * meta_clear_one_candidate
258 * clears the selected candidate
261 meta_clear_one_candidate(
262 struct metasingleconn *lsc,
266 lsc->candidate = META_NOT_CANDIDATE;
268 if ( !reallyclean ) {
273 ldap_unbind( lsc->ld );
277 if ( lsc->bound_dn != NULL ) {
278 free( lsc->bound_dn );
279 lsc->bound_dn = NULL;