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