Back to index

openldap  2.4.31
candidates.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 2001-2003 Pierangelo Masarati.
00006  * Portions Copyright 1999-2003 Howard Chu.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by the Howard Chu for inclusion
00019  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00020  * Masarati.
00021  */
00022 
00023 #include "portable.h"
00024 
00025 #include <stdio.h>
00026 #include "ac/string.h"
00027 
00028 #include "slap.h"
00029 #include "../back-ldap/back-ldap.h"
00030 #include "back-meta.h"
00031 
00032 /*
00033  * The meta-directory has one suffix, called <suffix>.
00034  * It handles a pool of target servers, each with a branch suffix
00035  * of the form <branch X>,<suffix>, where <branch X> may be empty.
00036  *
00037  * When the meta-directory receives a request with a request DN that belongs
00038  * to a branch, the corresponding target is invoked. When the request DN
00039  * does not belong to a specific branch, all the targets that
00040  * are compatible with the request DN are selected as candidates, and
00041  * the request is spawned to all the candidate targets
00042  *
00043  * A request is characterized by a request DN. The following cases are
00044  * handled:
00045  *     - the request DN is the suffix: <dn> == <suffix>,
00046  *            all the targets are candidates (search ...)
00047  *     - the request DN is a branch suffix: <dn> == <branch X>,<suffix>, or
00048  *     - the request DN is a subtree of a branch suffix:
00049  *            <dn> == <rdn>,<branch X>,<suffix>,
00050  *            the target is the only candidate.
00051  *
00052  * A possible extension will include the handling of multiple suffixes
00053  */
00054 
00055 static metasubtree_t *
00056 meta_subtree_match( metatarget_t *mt, struct berval *ndn, int scope )
00057 {
00058        metasubtree_t *ms = mt->mt_subtree;
00059 
00060        for ( ms = mt->mt_subtree; ms; ms = ms->ms_next ) {
00061               switch ( ms->ms_type ) {
00062               case META_ST_SUBTREE:
00063                      if ( dnIsSuffix( ndn, &ms->ms_dn ) ) {
00064                             return ms;
00065                      }
00066                      break;
00067 
00068               case META_ST_SUBORDINATE:
00069                      if ( dnIsSuffix( ndn, &ms->ms_dn ) &&
00070                             ( ndn->bv_len > ms->ms_dn.bv_len || scope != LDAP_SCOPE_BASE ) )
00071                      {
00072                             return ms;
00073                      }
00074                      break;
00075 
00076               case META_ST_REGEX:
00077                      /* NOTE: cannot handle scope */
00078                      if ( regexec( &ms->ms_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) {
00079                             return ms;
00080                      }
00081                      break;
00082               }
00083        }
00084 
00085        return NULL;
00086 }
00087 
00088 /*
00089  * returns 1 if suffix is candidate for dn, otherwise 0
00090  *
00091  * Note: this function should never be called if dn is the <suffix>.
00092  */
00093 int 
00094 meta_back_is_candidate(
00095        metatarget_t  *mt,
00096        struct berval *ndn,
00097        int           scope )
00098 {
00099        struct berval rdn;
00100        int d = ndn->bv_len - mt->mt_nsuffix.bv_len;
00101 
00102        if ( d >= 0 ) {
00103               if ( !dnIsSuffix( ndn, &mt->mt_nsuffix ) ) {
00104                      return META_NOT_CANDIDATE;
00105               }
00106 
00107               /*
00108                * |  match  | exclude |
00109                * +---------+---------+-------------------+
00110                * |    T    |    T    | not candidate     |
00111                * |    F    |    T    | continue checking |
00112                * +---------+---------+-------------------+
00113                * |    T    |    F    | candidate         |
00114                * |    F    |    F    | not candidate     |
00115                * +---------+---------+-------------------+
00116                */
00117                      
00118               if ( mt->mt_subtree ) {
00119                      int match = ( meta_subtree_match( mt, ndn, scope ) != NULL );
00120 
00121                      if ( !mt->mt_subtree_exclude ) {
00122                             return match ? META_CANDIDATE : META_NOT_CANDIDATE;
00123                      }
00124 
00125                      if ( match /* && mt->mt_subtree_exclude */ ) {
00126                             return META_NOT_CANDIDATE;
00127                      }
00128               }
00129 
00130               switch ( mt->mt_scope ) {
00131               case LDAP_SCOPE_SUBTREE:
00132               default:
00133                      return META_CANDIDATE;
00134 
00135               case LDAP_SCOPE_SUBORDINATE:
00136                      if ( d > 0 ) {
00137                             return META_CANDIDATE;
00138                      }
00139                      break;
00140 
00141               /* nearly useless; not allowed by config */
00142               case LDAP_SCOPE_ONELEVEL:
00143                      if ( d > 0 ) {
00144                             rdn.bv_val = ndn->bv_val;
00145                             rdn.bv_len = (ber_len_t)d - STRLENOF( "," );
00146                             if ( dnIsOneLevelRDN( &rdn ) ) {
00147                                    return META_CANDIDATE;
00148                             }
00149                      }
00150                      break;
00151 
00152               /* nearly useless; not allowed by config */
00153               case LDAP_SCOPE_BASE:
00154                      if ( d == 0 ) {
00155                             return META_CANDIDATE;
00156                      }
00157                      break;
00158               }
00159 
00160        } else /* if ( d < 0 ) */ {
00161               if ( !dnIsSuffix( &mt->mt_nsuffix, ndn ) ) {
00162                      return META_NOT_CANDIDATE;
00163               }
00164 
00165               switch ( scope ) {
00166               case LDAP_SCOPE_SUBTREE:
00167               case LDAP_SCOPE_SUBORDINATE:
00168                      /*
00169                       * suffix longer than dn, but common part matches
00170                       */
00171                      return META_CANDIDATE;
00172 
00173               case LDAP_SCOPE_ONELEVEL:
00174                      rdn.bv_val = mt->mt_nsuffix.bv_val;
00175                      rdn.bv_len = (ber_len_t)(-d) - STRLENOF( "," );
00176                      if ( dnIsOneLevelRDN( &rdn ) ) {
00177                             return META_CANDIDATE;
00178                      }
00179                      break;
00180               }
00181        }
00182 
00183        return META_NOT_CANDIDATE;
00184 }
00185 
00186 /*
00187  * meta_back_select_unique_candidate
00188  *
00189  * returns the index of the candidate in case it is unique, otherwise
00190  * META_TARGET_NONE if none matches, or
00191  * META_TARGET_MULTIPLE if more than one matches
00192  * Note: ndn MUST be normalized.
00193  */
00194 int
00195 meta_back_select_unique_candidate(
00196        metainfo_t    *mi,
00197        struct berval *ndn )
00198 {
00199        int    i, candidate = META_TARGET_NONE;
00200 
00201        for ( i = 0; i < mi->mi_ntargets; i++ ) {
00202               metatarget_t  *mt = mi->mi_targets[ i ];
00203 
00204               if ( meta_back_is_candidate( mt, ndn, LDAP_SCOPE_BASE ) ) {
00205                      if ( candidate == META_TARGET_NONE ) {
00206                             candidate = i;
00207 
00208                      } else {
00209                             return META_TARGET_MULTIPLE;
00210                      }
00211               }
00212        }
00213 
00214        return candidate;
00215 }
00216 
00217 /*
00218  * meta_clear_unused_candidates
00219  *
00220  * clears all candidates except candidate
00221  */
00222 int
00223 meta_clear_unused_candidates(
00224        Operation     *op,
00225        int           candidate )
00226 {
00227        metainfo_t    *mi = ( metainfo_t * )op->o_bd->be_private;
00228        int           i;
00229        SlapReply     *candidates = meta_back_candidates_get( op );
00230        
00231        for ( i = 0; i < mi->mi_ntargets; ++i ) {
00232               if ( i == candidate ) {
00233                      continue;
00234               }
00235               META_CANDIDATE_RESET( &candidates[ i ] );
00236        }
00237 
00238        return 0;
00239 }
00240 
00241 /*
00242  * meta_clear_one_candidate
00243  *
00244  * clears the selected candidate
00245  */
00246 int
00247 meta_clear_one_candidate(
00248        Operation     *op,
00249        metaconn_t    *mc,
00250        int           candidate )
00251 {
00252        metasingleconn_t     *msc = &mc->mc_conns[ candidate ];
00253 
00254        if ( msc->msc_ld != NULL ) {
00255 
00256 #ifdef DEBUG_205
00257               char   buf[ BUFSIZ ];
00258 
00259               snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p",
00260                      candidate, (void *)mc, (void *)msc->msc_ld );
00261               Debug( LDAP_DEBUG_ANY, "### %s %s\n",
00262                      op ? op->o_log_prefix : "", buf, 0 );
00263 #endif /* DEBUG_205 */
00264 
00265               ldap_unbind_ext( msc->msc_ld, NULL, NULL );
00266               msc->msc_ld = NULL;
00267        }
00268 
00269        if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
00270               ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
00271               BER_BVZERO( &msc->msc_bound_ndn );
00272        }
00273 
00274        if ( !BER_BVISNULL( &msc->msc_cred ) ) {
00275               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
00276               ber_memfree_x( msc->msc_cred.bv_val, NULL );
00277               BER_BVZERO( &msc->msc_cred );
00278        }
00279 
00280        msc->msc_mscflags = 0;
00281 
00282        return 0;
00283 }
00284