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 */ 62int 63meta_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 */ 132int 133meta_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 */ 160int 161meta_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 */ 184int 185meta_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