xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-meta/candidates.c (revision af56d1fe9956bd7c616e18c1b7f025f464618471)
1 /*	$NetBSD: candidates.c,v 1.1.1.3 2010/12/12 15:23:09 adam Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/servers/slapd/back-meta/candidates.c,v 1.28.2.7 2010/04/13 20:23:30 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2010 The OpenLDAP Foundation.
7  * Portions Copyright 2001-2003 Pierangelo Masarati.
8  * Portions Copyright 1999-2003 Howard Chu.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by the Howard Chu for inclusion
21  * in OpenLDAP Software and subsequently enhanced by Pierangelo
22  * Masarati.
23  */
24 
25 #include "portable.h"
26 
27 #include <stdio.h>
28 #include "ac/string.h"
29 
30 #include "slap.h"
31 #include "../back-ldap/back-ldap.h"
32 #include "back-meta.h"
33 
34 /*
35  * The meta-directory has one suffix, called <suffix>.
36  * It handles a pool of target servers, each with a branch suffix
37  * of the form <branch X>,<suffix>
38  *
39  * When the meta-directory receives a request with a dn that belongs
40  * to a branch, the corresponding target is invoked. When the dn
41  * does not belong to a specific branch, all the targets that
42  * are compatible with the dn are selected as candidates, and
43  * the request is spawned to all the candidate targets
44  *
45  * A request is characterized by a dn. The following cases are handled:
46  * 	- the dn is the suffix: <dn> == <suffix>,
47  * 		all the targets are candidates (search ...)
48  * 	- the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
49  * 	- the dn is a subtree of a branch suffix:
50  * 		<dn> == <rdn>,<branch X>,<suffix>,
51  * 		the target is the only candidate.
52  *
53  * A possible extension will include the handling of multiple suffixes
54  */
55 
56 
57 /*
58  * returns 1 if suffix is candidate for dn, otherwise 0
59  *
60  * Note: this function should never be called if dn is the <suffix>.
61  */
62 int
63 meta_back_is_candidate(
64 	metatarget_t	*mt,
65 	struct berval	*ndn,
66 	int		scope )
67 {
68 	if ( dnIsSuffix( ndn, &mt->mt_nsuffix ) ) {
69 		if ( mt->mt_subtree_exclude ) {
70 			int	i;
71 
72 			for ( i = 0; !BER_BVISNULL( &mt->mt_subtree_exclude[ i ] ); i++ ) {
73 				if ( dnIsSuffix( ndn, &mt->mt_subtree_exclude[ i ] ) ) {
74 					return META_NOT_CANDIDATE;
75 				}
76 			}
77 		}
78 
79 		switch ( mt->mt_scope ) {
80 		case LDAP_SCOPE_SUBTREE:
81 		default:
82 			return META_CANDIDATE;
83 
84 		case LDAP_SCOPE_SUBORDINATE:
85 			if ( ndn->bv_len > mt->mt_nsuffix.bv_len ) {
86 				return META_CANDIDATE;
87 			}
88 			break;
89 
90 		/* nearly useless; not allowed by config */
91 		case LDAP_SCOPE_ONELEVEL:
92 			if ( ndn->bv_len > mt->mt_nsuffix.bv_len ) {
93 				struct berval	rdn = *ndn;
94 
95 				rdn.bv_len -= mt->mt_nsuffix.bv_len
96 					+ STRLENOF( "," );
97 				if ( dnIsOneLevelRDN( &rdn ) ) {
98 					return META_CANDIDATE;
99 				}
100 			}
101 			break;
102 
103 		/* nearly useless; not allowed by config */
104 		case LDAP_SCOPE_BASE:
105 			if ( ndn->bv_len == mt->mt_nsuffix.bv_len ) {
106 				return META_CANDIDATE;
107 			}
108 			break;
109 		}
110 
111 		return META_NOT_CANDIDATE;
112 	}
113 
114 	if ( scope == LDAP_SCOPE_SUBTREE && dnIsSuffix( &mt->mt_nsuffix, ndn ) ) {
115 		/*
116 		 * suffix longer than dn, but common part matches
117 		 */
118 		return META_CANDIDATE;
119 	}
120 
121 	return META_NOT_CANDIDATE;
122 }
123 
124 /*
125  * meta_back_select_unique_candidate
126  *
127  * returns the index of the candidate in case it is unique, otherwise
128  * META_TARGET_NONE if none matches, or
129  * META_TARGET_MULTIPLE if more than one matches
130  * Note: ndn MUST be normalized.
131  */
132 int
133 meta_back_select_unique_candidate(
134 	metainfo_t	*mi,
135 	struct berval	*ndn )
136 {
137 	int	i, candidate = META_TARGET_NONE;
138 
139 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
140 		metatarget_t	*mt = mi->mi_targets[ i ];
141 
142 		if ( meta_back_is_candidate( mt, ndn, LDAP_SCOPE_BASE ) ) {
143 			if ( candidate == META_TARGET_NONE ) {
144 				candidate = i;
145 
146 			} else {
147 				return META_TARGET_MULTIPLE;
148 			}
149 		}
150 	}
151 
152 	return candidate;
153 }
154 
155 /*
156  * meta_clear_unused_candidates
157  *
158  * clears all candidates except candidate
159  */
160 int
161 meta_clear_unused_candidates(
162 	Operation	*op,
163 	int		candidate )
164 {
165 	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;
166 	int		i;
167 	SlapReply	*candidates = meta_back_candidates_get( op );
168 
169 	for ( i = 0; i < mi->mi_ntargets; ++i ) {
170 		if ( i == candidate ) {
171 			continue;
172 		}
173 		META_CANDIDATE_RESET( &candidates[ i ] );
174 	}
175 
176 	return 0;
177 }
178 
179 /*
180  * meta_clear_one_candidate
181  *
182  * clears the selected candidate
183  */
184 int
185 meta_clear_one_candidate(
186 	Operation	*op,
187 	metaconn_t	*mc,
188 	int		candidate )
189 {
190 	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
191 
192 	if ( msc->msc_ld != NULL ) {
193 
194 #ifdef DEBUG_205
195 		char	buf[ BUFSIZ ];
196 
197 		snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p",
198 			candidate, (void *)mc, (void *)msc->msc_ld );
199 		Debug( LDAP_DEBUG_ANY, "### %s %s\n",
200 			op ? op->o_log_prefix : "", buf, 0 );
201 #endif /* DEBUG_205 */
202 
203 		ldap_unbind_ext( msc->msc_ld, NULL, NULL );
204 		msc->msc_ld = NULL;
205 	}
206 
207 	if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
208 		ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
209 		BER_BVZERO( &msc->msc_bound_ndn );
210 	}
211 
212 	if ( !BER_BVISNULL( &msc->msc_cred ) ) {
213 		memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
214 		ber_memfree_x( msc->msc_cred.bv_val, NULL );
215 		BER_BVZERO( &msc->msc_cred );
216 	}
217 
218 	msc->msc_mscflags = 0;
219 
220 	return 0;
221 }
222 
223