]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/candidates.c
ee2bf0171fa611474acb771c3e59b3a8ffc71cb1
[openldap] / servers / slapd / back-meta / candidates.c
1 /*
2  * Copyright 1998-2001 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  *
5  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
6  *
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.
11  *
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:
15  *
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 
18  *    flaws in it.
19  *
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.
23  *
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
28  *    alterations.
29  *
30  * 4. This notice may not be removed or altered.
31  *
32  *
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.
38  *
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.
42  *
43  * The original copyright statement follows.
44  *
45  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
46  *
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:
50  *
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.
53  *
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.
57  *
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
61  *    documentation.
62  *
63  * 4. This notice may not be removed or altered.
64  *                
65  */
66
67 #include "portable.h"
68
69 #include <stdio.h>
70
71 #include "slap.h"
72 #include "../back-ldap/back-ldap.h"
73 #include "back-meta.h"
74
75 /*
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>
79  *
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
85  *
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.
93  *
94  * A possible extension will include the handling of multiple suffixes
95  */
96
97 /*
98  * returns 1 if suffix is candidate for dn, otherwise 0
99  *
100  * Note: this function should never be called if dn is the <suffix>.
101  */
102 int 
103 meta_back_is_candidate(
104                 const char      *nsuffix,
105                 const char      *ndn,
106                 int             ndnlen
107 )
108 {
109         int len = strlen( nsuffix );
110
111         if ( len > ndnlen ) {
112                 /*
113                  * suffix longer than dn
114                  */
115                 if ( ! DN_SEPARATOR( nsuffix[ ( len - ndnlen ) - 1 ] ) ) {
116                         /*
117                          * not a separator begins the possible common part
118                          */
119                         return META_NOT_CANDIDATE;
120                 }
121
122                 if ( strcmp( &nsuffix[ len - ndnlen ] , ndn ) == 0 ) {
123                         /*
124                          * Got it!
125                          */
126                         return META_CANDIDATE;
127                 }
128         }
129
130         if ( len < ndnlen && ! DN_SEPARATOR( ndn[ ( ndnlen - len ) - 1 ] ) ) {
131                 /*
132                  * not a separator begins the possible common part
133                  */
134                 return META_NOT_CANDIDATE;
135         }
136
137         if ( strcmp( nsuffix, &ndn[ ndnlen - len ] ) == 0 ) {
138                 /*
139                  * Got it!
140                  */
141                 return META_CANDIDATE;
142         }
143
144         return META_NOT_CANDIDATE;
145 }
146
147 /*
148  * meta_back_count_candidates
149  *
150  * returns a count of the possible candidate targets
151  * Note: dn MUST be normalized
152  */
153
154 int
155 meta_back_count_candidates(
156                 struct metainfo         *li,
157                 const char              *ndn
158 )
159 {
160         int i, cnt = 0, ndnlen = strlen( ndn );
161
162         /*
163          * I know assertions should not check run-time values;
164          * at present I didn't find a place for such checks
165          * after config.c
166          */
167         assert( li->targets != NULL );
168         assert( li->ntargets != 0 );
169
170         for ( i = 0; i < li->ntargets; ++i ) {
171                 if ( meta_back_is_candidate( li->targets[ i ]->suffix,
172                                         ndn, ndnlen ) ) {
173                         ++cnt;
174                 }
175         }
176
177         return cnt;
178 }
179
180 /*
181  * meta_back_is_candidate_unique
182  *
183  * checks whether a candidate is unique
184  * Note: dn MUST be normalized
185  */
186 int
187 meta_back_is_candidate_unique(
188                 struct metainfo         *li,
189                 const char              *ndn
190 )
191 {
192         return ( meta_back_count_candidates( li, ndn ) == 1 );
193 }
194
195 /*
196  * meta_back_select_unique_candidate
197  *
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.
201  */
202 int
203 meta_back_select_unique_candidate(
204                 struct metainfo         *li,
205                 const char              *ndn
206 )
207 {
208         int i, ndnlen;
209         
210         switch ( meta_back_count_candidates( li, ndn ) ) {
211         case 1:
212                 break;
213         case 0:
214         default:
215                 return ( li->defaulttarget == META_DEFAULT_TARGET_NONE
216                                 ? -1 : li->defaulttarget );
217         }
218
219         ndnlen = strlen( ndn );
220         for ( i = 0; i < li->ntargets; ++i ) {
221                 if ( meta_back_is_candidate( li->targets[ i ]->suffix,
222                                         ndn, ndnlen ) ) {
223                         return i;
224                 }
225         }
226
227         return -1;
228 }
229
230 /*
231  * meta_clear_unused_candidates
232  *
233  * clears all candidates except candidate
234  */
235 int
236 meta_clear_unused_candidates(
237                 struct metainfo         *li,
238                 struct metaconn         *lc,
239                 int                     candidate,
240                 int                     reallyclean
241 )
242 {
243         int i;
244         
245         for ( i = 0; i < li->ntargets; ++i ) {
246                 if ( i == candidate ) {
247                         continue;
248                 }
249                 meta_clear_one_candidate( lc->conns[ i ], reallyclean );
250         }
251
252         return 0;
253 }
254
255 /*
256  * meta_clear_one_candidate
257  *
258  * clears the selected candidate
259  */
260 int
261 meta_clear_one_candidate(
262                 struct metasingleconn   *lsc,
263                 int                     reallyclean
264 )
265 {
266         lsc->candidate = META_NOT_CANDIDATE;
267
268         if ( !reallyclean ) {
269                 return 0;
270         }
271
272         if ( lsc->ld ) {
273                 ldap_unbind( lsc->ld );
274                 lsc->ld = NULL;
275         }
276
277         if ( lsc->bound_dn != NULL ) {
278                 free( lsc->bound_dn );
279                 lsc->bound_dn = NULL;
280         }
281
282         return 0;
283 }
284