Diff for /servers/slapd/back-ldap/chain.c between versions 1.34 and 1.35

version 1.34, 2005/11/16 13:17:19 version 1.35, 2005/11/19 14:00:50
Line 1 Line 1
 /* chain.c - chain LDAP operations */  /* chain.c - chain LDAP operations */
 /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/chain.c,v 1.33 2005/11/04 00:42:11 ando Exp $ */  /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/chain.c,v 1.34 2005/11/16 13:17:19 ando Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 2003-2005 The OpenLDAP Foundation.   * Copyright 2003-2005 The OpenLDAP Foundation.
Line 17 Line 17
 /* ACKNOWLEDGEMENTS:  /* ACKNOWLEDGEMENTS:
  * This work was initially developed by the Howard Chu for inclusion   * This work was initially developed by the Howard Chu for inclusion
  * in OpenLDAP Software.   * in OpenLDAP Software.
    * This work was subsequently modified by Pierangelo Masarati.
  */   */
   
 #include "portable.h"  #include "portable.h"
Line 64  static int  sc_chainingBehavior; Line 65  static int  sc_chainingBehavior;
 static BackendInfo      *lback;  static BackendInfo      *lback;
   
 typedef struct ldap_chain_t {  typedef struct ldap_chain_t {
         struct ldapinfo         *lc_li;          /*
         unsigned                lc_flags;           * TODO: create a template ldapinfo_t that gets all common 
 #define LDAP_CHAIN_F_NONE               0x00U           * configuration items; then for each configured URI create
 #define LDAP_CHAIN_F_CHAINING           0x01U           * an entry in this tree; all the specific configuration
            * items get in the current URI structure.
            *
            * Then, for each referral, extract the URI and lookup the
            * related structure.  If configured to do so, allow URIs
            * not found in the structure to create a temporary one
            * that chains anonymously; maybe it can also be added to 
            * the tree?  Should be all configurable.
            */
           /* tree of configured[/generated] "uri" info */
           int                     lc_lai_count;
           ldap_avl_info_t         lc_lai;
   
           /* current configuration info */
           ldapinfo_t              *lc_cfg_li;
           /* "common" configuration info (all occurring before an "uri") */
           ldapinfo_t              *lc_common_li;
   
         ldap_pvt_thread_mutex_t lc_mutex;          unsigned                lc_flags;
   #define LDAP_CHAIN_F_NONE               (0x00U)
   #define LDAP_CHAIN_F_CHAINING           (0x01U)
   #define LDAP_CHAIN_F_CACHE_INFO         (0x10U)
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
         LDAPControl             lc_chaining_ctrl;          LDAPControl             lc_chaining_ctrl;
Line 77  typedef struct ldap_chain_t { Line 97  typedef struct ldap_chain_t {
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 } ldap_chain_t;  } ldap_chain_t;
   
   static int ldap_chain_db_init_one( BackendDB *be );
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 static int  static int
 chaining_control_add(  chaining_control_add(
Line 150  chaining_control_remove( Line 172  chaining_control_remove(
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
 static int  static int
   ldap_chain_uri_cmp( const void *c1, const void *c2 )
   {
           const ldapinfo_t        *li1 = (const ldapinfo_t *)c1;
           const ldapinfo_t        *li2 = (const ldapinfo_t *)c2;
   
           assert( li1->li_bvuri != NULL );
           assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) );
           assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) );
   
           assert( li2->li_bvuri != NULL );
           assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
           assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
   
           /* If local DNs don't match, it is definitely not a match */
           return ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] );
   }
   
   static int
   ldap_chain_uri_dup( void *c1, void *c2 )
   {
           ldapinfo_t      *li1 = (ldapinfo_t *)c1;
           ldapinfo_t      *li2 = (ldapinfo_t *)c2;
   
           assert( li1->li_bvuri != NULL );
           assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) );
           assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) );
   
           assert( li2->li_bvuri != NULL );
           assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) );
           assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) );
   
           /* Cannot have more than one shared session with same DN */
           if ( ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ) == 0 ) {
                   return -1;
           }
                   
           return 0;
   }
   
   static int
 ldap_chain_operational( Operation *op, SlapReply *rs )  ldap_chain_operational( Operation *op, SlapReply *rs )
 {  {
         /* Trap entries generated by back-ldap.          /* Trap entries generated by back-ldap.
Line 211  ldap_chain_cb_search_response( Operation Line 273  ldap_chain_cb_search_response( Operation
                         switch ( get_continuationBehavior( op ) ) {                          switch ( get_continuationBehavior( op ) ) {
                         case SLAP_CH_RESOLVE_CHAINING_REQUIRED:                          case SLAP_CH_RESOLVE_CHAINING_REQUIRED:
                                 op->o_callback->sc_private = LDAP_CH_ERR;                                  op->o_callback->sc_private = LDAP_CH_ERR;
                                 return -1;                                  return rs->sr_err = LDAP_X_CANNOT_CHAIN;
   
                         default:                          default:
                                 break;                                  break;
Line 241  ldap_chain_cb_response( Operation *op, S Line 303  ldap_chain_cb_response( Operation *op, S
         }          }
   
         if ( rs->sr_type == REP_RESULT ) {          if ( rs->sr_type == REP_RESULT ) {
                 op->o_callback->sc_private = LDAP_CH_RES;                  switch ( rs->sr_err ) {
                   case LDAP_COMPARE_TRUE:
                   case LDAP_COMPARE_FALSE:
                           if ( op->o_tag != LDAP_REQ_COMPARE ) {
                                   return rs->sr_err;
                           }
                           /* fallthru */
   
                   case LDAP_SUCCESS:
                           op->o_callback->sc_private = LDAP_CH_RES;
                           break;
   
                   case LDAP_REFERRAL:
   #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
                           if ( get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
                                   switch ( get_continuationBehavior( op ) ) {
                                   case SLAP_CH_RESOLVE_CHAINING_REQUIRED:
                                           op->o_callback->sc_private = LDAP_CH_ERR;
                                           return rs->sr_err = LDAP_X_CANNOT_CHAIN;
   
                                   default:
                                           break;
                                   }
                           }
   #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
                           break;
   
                   default:
                           return rs->sr_err;
                   }
   
         } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )          } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
         {          {
Line 261  ldap_chain_op( Line 352  ldap_chain_op(
 {  {
         slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;          slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;          ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
           ldapinfo_t      li = *lc->lc_common_li, *lip = NULL;
         struct ldapinfo *lip = lc->lc_li;          struct berval   bvuri[ 2 ] = { { 0 } };
         char            *save_url = NULL;  
         SlapReply       rs2 = { 0 };  
   
         /* NOTE: returned if ref is empty... */          /* NOTE: returned if ref is empty... */
         int             rc = LDAP_OTHER;          int             rc = LDAP_OTHER;
Line 275  ldap_chain_op( Line 364  ldap_chain_op(
         (void)chaining_control_add( lc, op, &ctrls );          (void)chaining_control_add( lc, op, &ctrls );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
         if ( lip->url != NULL ) {          li.li_bvuri = bvuri;
                 op->o_bd->be_private = lip;  
                 rc = ( *op_f )( op, &rs2 );  
                 rs->sr_err = rs2.sr_err;  
                 goto done;  
         }  
   
         save_url = lip->url;  
         lip->url = NULL;  
         op->o_bd->be_private = lip;  
   
         /* if we parse the URI then by no means   
          * we can cache stuff or reuse connections,   
          * because in back-ldap there's no caching  
          * based on the URI value, which is supposed  
          * to be set once for all (correct?) */  
         op->o_do_not_cache = 1;  
   
         for ( ; !BER_BVISNULL( ref ); ref++ ) {          for ( ; !BER_BVISNULL( ref ); ref++ ) {
                 LDAPURLDesc     *srv;                  LDAPURLDesc     *srv;
                 char            *save_dn;                  char            *save_dn;
                   int             temporary = 0;
                                                   
                 /* We're setting the URI of the first referral;                  /* We're setting the URI of the first referral;
                  * what if there are more?                   * what if there are more?
Line 328  Document: draft-ietf-ldapbis-protocol-27 Line 401  Document: draft-ietf-ldapbis-protocol-27
                 save_dn = srv->lud_dn;                  save_dn = srv->lud_dn;
                 srv->lud_dn = "";                  srv->lud_dn = "";
                 srv->lud_scope = LDAP_SCOPE_DEFAULT;                  srv->lud_scope = LDAP_SCOPE_DEFAULT;
                 lip->url = ldap_url_desc2str( srv );                  li.li_uri = ldap_url_desc2str( srv );
                 srv->lud_dn = save_dn;                  srv->lud_dn = save_dn;
                 ldap_free_urldesc( srv );                  ldap_free_urldesc( srv );
   
                 if ( lip->url == NULL ) {                  if ( li.li_uri == NULL ) {
                         /* try next */                          /* try next */
                         rc = LDAP_OTHER;                          rc = LDAP_OTHER;
                         continue;                          continue;
                 }                  }
   
                 rc = ( *op_f )( op, &rs2 );                  ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] );
                 rs->sr_err = rs2.sr_err;  
                   /* Searches for a ldapinfo in the avl tree */
                   ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );
                   lip = (ldapinfo_t *)avl_find( lc->lc_lai.lai_tree, 
                           (caddr_t)&li, ldap_chain_uri_cmp );
                   ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );
   
                   if ( lip != NULL ) {
                           op->o_bd->be_private = (void *)lip;
   
                 ldap_memfree( lip->url );                  } else {
                 lip->url = NULL;                          rc = ldap_chain_db_init_one( op->o_bd );
                           if ( rc != 0 ) {
                                   goto cleanup;
                           }
                           lip = (ldapinfo_t *)op->o_bd->be_private;
                           lip->li_uri = li.li_uri;
                           lip->li_bvuri = bvuri;
                           rc = lback->bi_db_open( op->o_bd );
                           if ( rc != 0 ) {
                                   (void)lback->bi_db_destroy( op->o_bd );
                                   goto cleanup;
                           }
                           temporary = 1;
                   }
   
                   rc = ( *op_f )( op, rs );
   
   cleanup:;
                   ldap_memfree( li.li_uri );
                   li.li_uri = NULL;
   
                   if ( temporary ) {
                           lip->li_uri = NULL;
                           lip->li_bvuri = NULL;
   #if 0   /* does not exist yet */
                           (void)lback->bi_db_close( op->o_bd );
   #endif
                           (void)lback->bi_db_destroy( op->o_bd );
                   }
                                   
                 if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {                  if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
                         break;                          break;
                 }                  }
         }          }
   
         lip->url = save_url;  
   
 done:;  
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
         (void)chaining_control_remove( op, &ctrls );          (void)chaining_control_remove( op, &ctrls );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
Line 367  ldap_chain_response( Operation *op, Slap Line 473  ldap_chain_response( Operation *op, Slap
         slap_callback   *sc = op->o_callback,          slap_callback   *sc = op->o_callback,
                         sc2 = { 0 };                          sc2 = { 0 };
         int             rc = 0;          int             rc = 0;
         int             cache = op->o_do_not_cache;          const char      *matched;
         char            *matched;  
         BerVarray       ref;          BerVarray       ref;
         struct berval   ndn = op->o_ndn;          struct berval   ndn = op->o_ndn;
   
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;  
         struct ldapinfo *lip = lc->lc_li;  
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
         int             sr_err = rs->sr_err;          int             sr_err = rs->sr_err;
         slap_reply_t    sr_type = rs->sr_type;          slap_reply_t    sr_type = rs->sr_type;
Line 413  ldap_chain_response( Operation *op, Slap Line 515  ldap_chain_response( Operation *op, Slap
         }          }
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
         ldap_pvt_thread_mutex_lock( &lc->lc_mutex );  
   
         /*          /*
          * TODO: add checks on who/when chain operations; e.g.:           * TODO: add checks on who/when chain operations; e.g.:
          *   a) what identities are authorized           *   a) what identities are authorized
Line 455  ldap_chain_response( Operation *op, Slap Line 555  ldap_chain_response( Operation *op, Slap
                 op->o_conn = conn;                  op->o_conn = conn;
                 }                  }
                 break;                  break;
   
         case LDAP_REQ_ADD:          case LDAP_REQ_ADD:
                 rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );                  rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
                 break;                  break;
   
         case LDAP_REQ_DELETE:          case LDAP_REQ_DELETE:
                 rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );                  rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );
                 break;                  break;
   
         case LDAP_REQ_MODRDN:          case LDAP_REQ_MODRDN:
                 rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref );                  rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref );
                 break;                  break;
   
         case LDAP_REQ_MODIFY:          case LDAP_REQ_MODIFY:
                 rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref );                  rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref );
                 break;                  break;
   
         case LDAP_REQ_COMPARE:          case LDAP_REQ_COMPARE:
                 rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref );                  rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref );
                   if ( rs->sr_err == LDAP_COMPARE_TRUE || rs->sr_err == LDAP_COMPARE_FALSE ) {
                           rc = LDAP_SUCCESS;
                   }
                 break;                  break;
   
         case LDAP_REQ_SEARCH:          case LDAP_REQ_SEARCH:
                 if ( rs->sr_type == REP_SEARCHREF ) {                  if ( rs->sr_type == REP_SEARCHREF ) {
                           ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
                           ldapinfo_t      li = *lc->lc_common_li, *lip = NULL;
                           struct berval   bvuri[ 2 ] = { { 0 } };
   
                         struct berval   *curr = ref,                          struct berval   *curr = ref,
                                         odn = op->o_req_dn,                                          odn = op->o_req_dn,
                                         ondn = op->o_req_ndn;                                          ondn = op->o_req_ndn;
                         char            *save_url = NULL;  
                         SlapReply       rs2 = { 0 };  
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
                         LDAPControl     **ctrls = NULL;                          LDAPControl     **ctrls = NULL;
Line 488  ldap_chain_response( Operation *op, Slap Line 599  ldap_chain_response( Operation *op, Slap
   
                         sc2.sc_response = ldap_chain_cb_search_response;                          sc2.sc_response = ldap_chain_cb_search_response;
   
                         save_url = lip->url;  
                         lip->url = NULL;  
                         op->o_bd->be_private = lip;  
                           
                         /* if we parse the URI then by no means                           /* if we parse the URI then by no means 
                          * we can cache stuff or reuse connections,                            * we can cache stuff or reuse connections, 
                          * because in back-ldap there's no caching                           * because in back-ldap there's no caching
                          * based on the URI value, which is supposed                           * based on the URI value, which is supposed
                          * to be set once for all (correct?) */                           * to be set once for all (correct?) */
                         op->o_do_not_cache = 1;                          li.li_bvuri = bvuri;
   
                         /* copy the private info because we need to modify it */  
                         for ( ; !BER_BVISNULL( &curr[0] ); curr++ ) {                          for ( ; !BER_BVISNULL( &curr[0] ); curr++ ) {
                                 LDAPURLDesc     *srv;                                  LDAPURLDesc     *srv;
                                 char            *save_dn;                                  char            *save_dn;
                                   int             temporary = 0;
   
                                 /* parse reference and use                                  /* parse reference and use
                                  * proto://[host][:port]/ only */                                   * proto://[host][:port]/ only */
Line 519  ldap_chain_response( Operation *op, Slap Line 625  ldap_chain_response( Operation *op, Slap
                                 save_dn = srv->lud_dn;                                  save_dn = srv->lud_dn;
                                 srv->lud_dn = "";                                  srv->lud_dn = "";
                                 srv->lud_scope = LDAP_SCOPE_DEFAULT;                                  srv->lud_scope = LDAP_SCOPE_DEFAULT;
                                 lip->url = ldap_url_desc2str( srv );                                  li.li_uri = ldap_url_desc2str( srv );
                                 if ( lip->url != NULL ) {                                  if ( li.li_uri != NULL ) {
                                         ber_str2bv_x( save_dn, 0, 1, &op->o_req_dn,                                          ber_str2bv_x( save_dn, 0, 1, &op->o_req_dn,
                                                         op->o_tmpmemctx );                                                          op->o_tmpmemctx );
                                         ber_dupbv_x( &op->o_req_ndn, &op->o_req_dn,                                          ber_dupbv_x( &op->o_req_ndn, &op->o_req_dn,
Line 530  ldap_chain_response( Operation *op, Slap Line 636  ldap_chain_response( Operation *op, Slap
                                 srv->lud_dn = save_dn;                                  srv->lud_dn = save_dn;
                                 ldap_free_urldesc( srv );                                  ldap_free_urldesc( srv );
   
                                 if ( lip->url == NULL ) {                                  if ( li.li_uri == NULL ) {
                                         /* try next */                                          /* try next */
                                         rs->sr_err = LDAP_OTHER;                                          rs->sr_err = LDAP_OTHER;
                                         continue;                                          continue;
                                 }                                  }
   
                                   ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] );
   
                                   /* Searches for a ldapinfo in the avl tree */
                                   ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );
                                   lip = (ldapinfo_t *)avl_find( lc->lc_lai.lai_tree, 
                                           (caddr_t)&li, ldap_chain_uri_cmp );
                                   ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );
   
                                   if ( lip != NULL ) {
                                           op->o_bd->be_private = (void *)lip;
   
                                   } else {
                                           /* if none is found, create a temporary... */
                                           rc = ldap_chain_db_init_one( op->o_bd );
                                           if ( rc != 0 ) {
                                                   goto cleanup;
                                           }
                                           lip = (ldapinfo_t *)op->o_bd->be_private;
                                           lip->li_uri = li.li_uri;
                                           lip->li_bvuri = bvuri;
                                           rc = lback->bi_db_open( op->o_bd );
                                           if ( rc != 0 ) {
                                                   (void)lback->bi_db_destroy( op->o_bd );
                                                   goto cleanup;
                                           }
                                           temporary = 1;
                                   }
   
                                 /* FIXME: should we also copy filter and scope?                                  /* FIXME: should we also copy filter and scope?
                                  * according to RFC3296, no */                                   * according to RFC3296, no */
                                 rc = lback->bi_op_search( op, &rs2 );                                  rc = lback->bi_op_search( op, rs );
                                 rs->sr_err = rs2.sr_err;  
   
                                 ldap_memfree( lip->url );  cleanup:;
                                 lip->url = NULL;                                  ldap_memfree( li.li_uri );
                                   li.li_uri = NULL;
   
                                 op->o_tmpfree( op->o_req_dn.bv_val,                                  op->o_tmpfree( op->o_req_dn.bv_val,
                                                 op->o_tmpmemctx );                                                  op->o_tmpmemctx );
                                 op->o_tmpfree( op->o_req_ndn.bv_val,                                  op->o_tmpfree( op->o_req_ndn.bv_val,
                                                 op->o_tmpmemctx );                                                  op->o_tmpmemctx );
   
                                   if ( temporary ) {
                                           lip->li_uri = NULL;
                                           lip->li_bvuri = NULL;
   #if 0   /* does not exist yet */
                                           (void)lback->bi_db_close( op->o_bd );
   #endif
                                           (void)lback->bi_db_destroy( op->o_bd );
                                   }
                   
                                 if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {                                  if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
                                         break;                                          break;
                                 }                                  }
Line 561  ldap_chain_response( Operation *op, Slap Line 703  ldap_chain_response( Operation *op, Slap
                         (void)chaining_control_remove( op, &ctrls );                          (void)chaining_control_remove( op, &ctrls );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
                         lip->url = save_url;  
   
                         op->o_req_dn = odn;                          op->o_req_dn = odn;
                         op->o_req_ndn = ondn;                          op->o_req_ndn = ondn;
                         rs->sr_type = REP_SEARCHREF;                          rs->sr_type = REP_SEARCHREF;
Line 577  ldap_chain_response( Operation *op, Slap Line 717  ldap_chain_response( Operation *op, Slap
                         rc = ldap_chain_op( op, rs, lback->bi_op_search, ref );                          rc = ldap_chain_op( op, rs, lback->bi_op_search, ref );
                 }                  }
                 break;                  break;
   
         case LDAP_REQ_EXTENDED:          case LDAP_REQ_EXTENDED:
                 rc = ldap_chain_op( op, rs, lback->bi_extended, ref );                  rc = ldap_chain_op( op, rs, lback->bi_extended, ref );
                 /* FIXME: ldap_back_extended() by design                   /* FIXME: ldap_back_extended() by design 
                  * doesn't send result; frontend is expected                   * doesn't send result; frontend is expected
                  * to send it... */                   * to send it... */
                   /* FIXME: what aboit chaining? */
                 if ( rc != SLAPD_ABANDON ) {                  if ( rc != SLAPD_ABANDON ) {
                         send_ldap_extended( op, rs );                          send_ldap_extended( op, rs );
                         rc = LDAP_SUCCESS;                          rc = LDAP_SUCCESS;
                 }                  }
                   sc2.sc_private = LDAP_CH_RES;
                 break;                  break;
   
         default:          default:
                 rc = SLAP_CB_CONTINUE;                  rc = SLAP_CB_CONTINUE;
                 break;                  break;
         }          }
   
           switch ( rc ) {
           case SLAPD_ABANDON:
                   goto dont_chain;
   
           case LDAP_SUCCESS:
           case LDAP_REFERRAL:
                   /* slapd-ldap sent response */
                   assert( sc2.sc_private == LDAP_CH_RES );
                   break;
   
           default:
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
         if ( rc != LDAP_SUCCESS || sc2.sc_private == LDAP_CH_ERR ) {                  if ( sc2.sc_private == LDAP_CH_ERR && rs->sr_err == LDAP_X_CANNOT_CHAIN ) {
                 if ( rs->sr_err == LDAP_X_CANNOT_CHAIN ) {  
                         goto cannot_chain;                          goto cannot_chain;
                 }                  }
   
Line 604  cannot_chain:; Line 758  cannot_chain:;
                         op->o_callback = NULL;                          op->o_callback = NULL;
                         send_ldap_error( op, rs, LDAP_X_CANNOT_CHAIN,                          send_ldap_error( op, rs, LDAP_X_CANNOT_CHAIN,
                                 "operation cannot be completed without chaining" );                                  "operation cannot be completed without chaining" );
                         break;                          goto dont_chain;
   
                 default:                  default:
   #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
                         rc = SLAP_CB_CONTINUE;                          rc = SLAP_CB_CONTINUE;
                         rs->sr_err = sr_err;                          rs->sr_err = sr_err;
                         rs->sr_type = sr_type;                          rs->sr_type = sr_type;
                           rs->sr_matched = matched;
                           rs->sr_ref = ref;
   #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
                         break;                          break;
                 }                  }
                 goto dont_chain;  
         }  
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
           }
   
         if ( sc2.sc_private == LDAP_CH_NONE ) {          if ( sc2.sc_private == LDAP_CH_NONE && rc != SLAPD_ABANDON ) {
                 op->o_callback = NULL;                  op->o_callback = NULL;
                 rc = rs->sr_err = slap_map_api2result( rs );                  rc = rs->sr_err = slap_map_api2result( rs );
                 send_ldap_result( op, rs );                  send_ldap_result( op, rs );
Line 625  cannot_chain:; Line 782  cannot_chain:;
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 dont_chain:;  dont_chain:;
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
         op->o_do_not_cache = cache;          rs->sr_err = sr_err;
           rs->sr_type = sr_type;
           rs->sr_matched = matched;
           rs->sr_ref = ref;
         op->o_bd->be_private = private;          op->o_bd->be_private = private;
         op->o_callback = sc;          op->o_callback = sc;
         op->o_ndn = ndn;          op->o_ndn = ndn;
         rs->sr_matched = matched;  
         rs->sr_ref = ref;  
   
         ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );  
   
         return rc;          return rc;
 }  }
Line 664  str2chain( const char *s ) Line 820  str2chain( const char *s )
 }  }
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
   /*
    * configuration...
    */
   
 enum {  enum {
         PC_CHAINING = 1          PC_CHAINING = 1
 };  };
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 static ConfigDriver chain_cf_gen;  static ConfigDriver chain_cf_gen;
 static ConfigCfAdd chain_cfadd;  
 #endif  #endif
   static ConfigCfAdd chain_cfadd;
 static ConfigLDAPadd chain_ldadd;  static ConfigLDAPadd chain_ldadd;
   
 static ConfigTable chaincfg[] = {  static ConfigTable chaincfg[] = {
Line 703  static ConfigOCs chainocs[] = { Line 863  static ConfigOCs chainocs[] = {
 static int  static int
 chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )  chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 {  {
         if ( p->ce_type != Cft_Overlay || !p->ce_bi ||          if ( p->ce_type != Cft_Overlay
                 p->ce_bi->bi_cf_ocs != chainocs )                  || !p->ce_bi
                   || p->ce_bi->bi_cf_ocs != chainocs )
           {
                 return LDAP_CONSTRAINT_VIOLATION;                  return LDAP_CONSTRAINT_VIOLATION;
           }
   
         return LDAP_SUCCESS;          return LDAP_SUCCESS;
 }  }
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR  typedef struct ldap_chain_cfadd_apply_t {
           Operation       *op;
           SlapReply       *rs;
           Entry           *p;
           ConfigArgs      *ca;
           int             count;
   } ldap_chain_cfadd_apply_t;
   
   static int
   ldap_chain_cfadd_apply( void *datum, void *arg )
   {
           ldapinfo_t                      *li = (ldapinfo_t *)datum;
           ldap_chain_cfadd_apply_t        *lca = (ldap_chain_cfadd_apply_t *)arg;
   
           struct berval                   bv;
   
           /* FIXME: should not hardcode "olcDatabase" here */
           bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
                   "olcDatabase={%d}%s", lca->count, lback->bi_type );
           bv.bv_val = lca->ca->msg;
   
           lca->ca->be->be_private = (void *)li;
           config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
                   &bv, lback->bi_cf_ocs, &chainocs[1] );
   
           lca->count++;
   
           return 0;
   }
   
 static int  static int
 chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )  chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )
Line 719  chain_cfadd( Operation *op, SlapReply *r Line 910  chain_cfadd( Operation *op, SlapReply *r
         slap_overinst   *on = (slap_overinst *)pe->ce_bi;          slap_overinst   *on = (slap_overinst *)pe->ce_bi;
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;          ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
         void            *priv = (void *)ca->be->be_private;          void            *priv = (void *)ca->be->be_private;
         struct berval   bv;  
   
         /* FIXME: should not hardcode "olcDatabase" here */  
         bv.bv_len = sprintf( ca->msg, "olcDatabase=%s", lback->bi_type );  
         bv.bv_val = ca->msg;  
   
         /* We can only create this entry if the database is table-driven */  
         if ( lback->bi_cf_ocs ) {          if ( lback->bi_cf_ocs ) {
                 ca->be->be_private = (void *)lc->lc_li;                  ldap_chain_cfadd_apply_t        lca = { 0 };
                 config_build_entry( op, rs, pe, ca, &bv, lback->bi_cf_ocs, &chainocs[1] );  
                   lca.op = op;
                   lca.rs = rs;
                   lca.p = p;
                   lca.ca = ca;
                   lca.count = -1;
   
                   (void)ldap_chain_cfadd_apply( (void *)lc->lc_common_li, (void *)&lca );
   
                   (void)avl_apply( lc->lc_lai.lai_tree, ldap_chain_cfadd_apply,
                           &lca, 1, AVL_INORDER );
   
                 ca->be->be_private = priv;                  ca->be->be_private = priv;
         }          }
   
         return 0;          return 0;
 }  }
   
   #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
   
 static slap_verbmasks chaining_mode[] = {  static slap_verbmasks chaining_mode[] = {
         { BER_BVC("referralsRequired"),         LDAP_REFERRALS_REQUIRED },          { BER_BVC("referralsRequired"),         LDAP_REFERRALS_REQUIRED },
         { BER_BVC("referralsPreferred"),        LDAP_REFERRALS_PREFERRED },          { BER_BVC("referralsPreferred"),        LDAP_REFERRALS_PREFERRED },
Line 931  chain_cf_gen( ConfigArgs *c ) Line 1129  chain_cf_gen( ConfigArgs *c )
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
 static int  static int
   ldap_chain_db_init(
           BackendDB *be )
   {
           slap_overinst   *on = (slap_overinst *)be->bd_info;
           ldap_chain_t    *lc = NULL;
           int             rc;
           BackendDB       bd = *be;
   
           if ( lback == NULL ) {
                   lback = backend_info( "ldap" );
   
                   if ( lback == NULL ) {
                           return -1;
                   }
           }
   
           lc = ch_malloc( sizeof( ldap_chain_t ) );
           memset( lc, 0, sizeof( ldap_chain_t ) );
   
           bd.be_private = NULL;
           rc = lback->bi_db_init( &bd );
           lc->lc_cfg_li = lc->lc_common_li = (ldapinfo_t *)bd.be_private;
           on->on_bi.bi_private = (void *)lc;
   
           return rc;
   }
   
   static int
 ldap_chain_db_config(  ldap_chain_db_config(
         BackendDB       *be,          BackendDB       *be,
         const char      *fname,          const char      *fname,
Line 938  ldap_chain_db_config( Line 1164  ldap_chain_db_config(
         int             argc,          int             argc,
         char            **argv )          char            **argv )
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          slap_overinst   *on = (slap_overinst *)be->bd_info;
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;          ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
         char            *argv0 = NULL;  
         int             rc;  
         BackendDB       db = *be;  
   
           int             rc = SLAP_CONF_UNKNOWN;
                   
           /* Something for the cache database? */
         if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {          if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {
                 argv0 = argv[ 0 ];                  char            *save_argv0 = argv[ 0 ];
                 argv[ 0 ] = &argv[ 0 ][ STRLENOF( "chain-" ) ];                  BackendInfo     *bd_info = bd_info;
                   void            *be_private = be->be_private;
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR                  ConfigOCs       *be_cf_ocs = be->be_cf_ocs;
                 if ( strcasecmp( argv[ 0 ], "chaining" ) == 0 ) {                  int             is_uri = 0;
                         char                    **tmpargv = argv;  
                         BerElementBuffer        berbuf;                  argv[ 0 ] += STRLENOF( "chain-" );
                         BerElement              *ber = (BerElement *)&berbuf;  
                         int                     resolve = -1,                  /* TODO: create a new structure and, after parsing the URI,
                                                 continuation = -1,                   * put it in the lc->lc_lai tree */
                                                 iscritical = 0;                  if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) {
                         Operation               op = { 0 };                          rc = ldap_chain_db_init_one( be );
                         SlapReply               rs = { 0 };                          if ( rc != 0 ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                         lc->lc_chaining_ctrlflag = 0;                                          "underlying slapd-ldap initialization failed\n.",
                                           fname, lineno, 0 );
                         for ( argc--, tmpargv++; argc > 0; argc--, tmpargv++ ) {                                  return 1;
                                 if ( strncasecmp( tmpargv[ 0 ], "resolve=", STRLENOF( "resolve=" ) ) == 0 ) {                          }
                                         resolve = str2chain( tmpargv[ 0 ] + STRLENOF( "resolve=" ) );                          lc->lc_cfg_li = be->be_private;
                                         if ( resolve == -1 ) {                          is_uri = 1;
                                                 fprintf( stderr, "%s line %d: "                  }
                                                         "illegal <resolve> value %s "  
                                                         "in \"chain-chaining>\"\n",  
                                                         fname, lineno, tmpargv[ 0 ] );  
                                                 return 1;  
                                         }  
   
                                 } else if ( strncasecmp( tmpargv[ 0 ], "continuation=", STRLENOF( "continuation=" ) ) == 0 ) {                  be->bd_info = lback;
                                         continuation = str2chain( tmpargv[ 0 ] + STRLENOF( "continuation=" ) );                  be->be_private = (void *)lc->lc_cfg_li;
                                         if ( continuation == -1 ) {                  be->be_cf_ocs = lback->bi_cf_ocs;
                                                 fprintf( stderr, "%s line %d: "  
                                                         "illegal <continuation> value %s "                  rc = config_generic_wrapper( be, fname, lineno, argc, argv );
                                                         "in \"chain-chaining\"\n",  
                                                         fname, lineno, tmpargv[ 0 ] );                  argv[ 0 ] = save_argv0;
                                                 return 1;                  be->be_cf_ocs = be_cf_ocs;
                                         }                  be->be_private = be_private;
                   be->bd_info = bd_info;
   
                   if ( is_uri ) {
   private_destroy:;
                           if ( rc != 0 ) {
                                   BackendDB               db = *be;
   
                                   db.bd_info = lback;
                                   db.be_private = (void *)lc->lc_cfg_li;
                                   lback->bi_db_destroy( &db );
                                   lc->lc_cfg_li = NULL;
   
                                 } else if ( strcasecmp( tmpargv[ 0 ], "critical" ) == 0 ) {                          } else {
                                         iscritical = 1;                                  if ( lc->lc_cfg_li->li_bvuri == NULL
                                           || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] )
                                           || !BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 1 ] ) )
                                   {
                                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                                   "no URI list allowed in slapo-chain.\n",
                                                   fname, lineno, 0 );
                                           rc = 1;
                                           goto private_destroy;
                                   }
   
                                 } else {                                  if ( avl_insert( &lc->lc_lai.lai_tree,
                                         fprintf( stderr, "%s line %d: "                                          (caddr_t)lc->lc_cfg_li,
                                                 "unknown option in \"chain-chaining\"\n",                                          ldap_chain_uri_cmp, ldap_chain_uri_dup ) )
                                                 fname, lineno );                                  {
                                         return 1;                                          Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                                   "duplicate URI in slapo-chain.\n",
                                                   fname, lineno, 0 );
                                           rc = 1;
                                           goto private_destroy;
                                 }                                  }
                         }                          }
                   }
           }
           
           return rc;
   }
   
                         if ( resolve != -1 || continuation != -1 ) {  enum db_which {
                                 int     err;          db_open = 0,
           db_close,
           db_destroy,
   
                                 if ( resolve == -1 ) {          db_last
                                         /* default */  };
                                         resolve = SLAP_CHAINING_DEFAULT;  
                                 }  
   
                                 ber_init2( ber, NULL, LBER_USE_DER );  typedef struct ldap_chain_db_apply_t {
           BackendDB       *be;
           BI_db_func      *func;
   } ldap_chain_db_apply_t;
   
                                 err = ber_printf( ber, "{e" /* } */, resolve );  static int
                                 if ( err == -1 ) {  ldap_chain_db_apply( void *datum, void *arg )
                                         ber_free( ber, 1 );  {
                                         fprintf( stderr, "%s line %d: "          ldapinfo_t              *li = (ldapinfo_t *)datum;
                                                 "chaining behavior control encoding error!\n",          ldap_chain_db_apply_t   *lca = (ldap_chain_db_apply_t *)arg;
                                                 fname, lineno );  
                                         return 1;  
                                 }  
   
                                 if ( continuation > -1 ) {          lca->be->be_private = (void *)li;
                                         err = ber_printf( ber, "e", continuation );  
                                         if ( err == -1 ) {  
                                                 ber_free( ber, 1 );  
                                                 fprintf( stderr, "%s line %d: "  
                                                         "chaining behavior control encoding error!\n",  
                                                         fname, lineno );  
                                                 return 1;  
                                         }  
                                 }  
   
                                 err = ber_printf( ber, /* { */ "N}" );          return lca->func( lca->be );
                                 if ( err == -1 ) {  }
                                         ber_free( ber, 1 );  
                                         fprintf( stderr, "%s line %d: "  
                                                 "chaining behavior control encoding error!\n",  
                                                 fname, lineno );  
                                         return 1;  
                                 }  
   
                                 if ( ber_flatten2( ber, &lc->lc_chaining_ctrl.ldctl_value, 0 ) == -1 ) {  static int
                                         exit( EXIT_FAILURE );  ldap_chain_db_func(
                                 }          BackendDB *be,
           enum db_which which
   )
   {
           slap_overinst   *on = (slap_overinst *)be->bd_info;
           ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
   
                         } else {          int             rc = 0;
                                 BER_BVZERO( &lc->lc_chaining_ctrl.ldctl_value );  
                         }  
   
                         lc->lc_chaining_ctrl.ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;          if ( lc ) {
                         lc->lc_chaining_ctrl.ldctl_iscritical = iscritical;                  BI_db_func      *func = (&lback->bi_db_open)[ which ];
   
                         if ( ldap_chain_parse_ctrl( &op, &rs, &lc->lc_chaining_ctrl ) != LDAP_SUCCESS )                  if ( func != NULL ) {
                         {                          BackendDB               db = *be;
                                 fprintf( stderr, "%s line %d: "  
                                         "unable to parse chaining control%s%s\n",                          db.bd_info = lback;
                                         fname, lineno,                          db.be_private = lc->lc_common_li;
                                         rs.sr_text ? ": " : "",  
                                         rs.sr_text ? rs.sr_text : "" );                          rc = func( &db );
                                 return 1;  
                           if ( rc != 0 ) {
                                   return rc;
                         }                          }
   
                         lc->lc_chaining_ctrlflag = op.o_chaining;                          if ( lc->lc_lai.lai_tree != NULL ) {
                                   ldap_chain_db_apply_t   lca;
   
                         lc->lc_flags |= LDAP_CHAIN_F_CHAINING;                                  lca.be = &db;
                                   lca.func = func;
   
                         rc = 0;                                  rc = avl_apply( lc->lc_lai.lai_tree,
                         goto done;                                          ldap_chain_db_apply, (void *)&lca,
                                           1, AVL_INORDER ) != AVL_NOMORE;
                           }
                 }                  }
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */  
         }          }
   
         db.be_cf_ocs = lback->bi_cf_ocs;          return rc;
         db.be_private = lc->lc_li;  }
         rc = lback->bi_db_config( &db, fname, lineno, argc, argv );  
   
 done:;  static int
         if ( argv0 ) {  ldap_chain_db_open(
                 argv[ 0 ] = argv0;          BackendDB       *be )
   {
   #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
           int     rc = 0;
   
           rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
           if ( rc != 0 ) {
                   return rc;
         }          }
   #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
   
         return rc;          /* FIXME: right now slapd-ldap has no open function;
            * in case one is introduced, this needs be fixed */
   
           return ldap_chain_db_func( be, db_open );
 }  }
   
 static int  static int
 ldap_chain_db_init(  ldap_chain_db_close(
         BackendDB *be )          BackendDB       *be )
 {  {
         slap_overinst   *on = (slap_overinst *)be->bd_info;          return ldap_chain_db_func( be, db_close );
         ldap_chain_t    *lc = NULL;  }
         int             rc;  
         BackendDB       bd = *be;  
   
         if ( lback == NULL ) {  
                 lback = backend_info( "ldap" );  
   
                 if ( lback == NULL ) {  static int
                         return -1;  ldap_chain_db_destroy(
                 }          BackendDB       *be )
         }  {
           slap_overinst   *on = (slap_overinst *) be->bd_info;
           ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
   
         lc = ch_malloc( sizeof( ldap_chain_t ) );          int             rc;
         memset( lc, 0, sizeof( ldap_chain_t ) );  
   
         ldap_pvt_thread_mutex_init( &lc->lc_mutex );          rc = ldap_chain_db_func( be, db_destroy );
   
         bd.be_private = NULL;          if ( lc ) {
         rc = lback->bi_db_init( &bd );                  ch_free( lc );
         lc->lc_li = (struct ldapinfo *)bd.be_private;          }
         on->on_bi.bi_private = (void *)lc;  
   
         return rc;          return rc;
 }  }
   
 static int  static int
 ldap_chain_db_open(  ldap_chain_db_init_one(
         BackendDB *be          BackendDB       *be )
 )  
 {  {
         int     rc = 0;          slap_overinst   *on = (slap_overinst *)be->bd_info;
           ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
   
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR          BackendDB       db = *be;
         rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );          int             t;
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */          ldapinfo_t      *li;
   
         return rc;          db.bd_info = lback;
           db.be_private = NULL;
           t = lback->bi_db_init( &db );
           if ( t != 0 ) {
                   return t;
           }
           li = (ldapinfo_t *)db.be_private;
   
           /* copy common data */
           li->li_nretries = lc->lc_common_li->li_nretries;
           li->li_flags = lc->lc_common_li->li_flags;
           li->li_version = lc->lc_common_li->li_version;
           for ( t = 0; t < LDAP_BACK_OP_LAST; t++ ) {
                   li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ];
           }
   
           be->be_private = li;
   
           return 0;
 }  }
   
   typedef struct ldap_chain_conn_apply_t {
           BackendDB       *be;
           Connection      *conn;
   } ldap_chain_conn_apply_t;
   
 static int  static int
 ldap_chain_db_destroy(  ldap_chain_conn_apply( void *datum, void *arg )
         BackendDB *be  
 )  
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          ldapinfo_t              *li = (ldapinfo_t *)datum;
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;          ldap_chain_conn_apply_t *lca = (ldap_chain_conn_apply_t *)arg;
         void            *private = be->be_private;  
         int             rc;  
   
         be->be_private = (void *)lc->lc_li;          lca->be->be_private = (void *)li;
         rc = lback->bi_db_destroy( be );  
         ldap_pvt_thread_mutex_destroy( &lc->lc_mutex );          return lback->bi_connection_destroy( lca->be, lca->conn );
         ch_free( lc );  
         on->on_bi.bi_private = NULL;  
         be->be_private = private;  
         return rc;  
 }  }
   
 static int  static int
Line 1144  ldap_chain_connection_destroy( Line 1407  ldap_chain_connection_destroy(
         Connection *conn          Connection *conn
 )  )
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          slap_overinst           *on = (slap_overinst *) be->bd_info;
         ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;          ldap_chain_t            *lc = (ldap_chain_t *)on->on_bi.bi_private;
         void            *private = be->be_private;          void                    *private = be->be_private;
         int             rc;          ldap_chain_conn_apply_t lca;
           int                     rc;
         be->be_private = (void *)lc->lc_li;  
         rc = lback->bi_connection_destroy( be, conn );          be->be_private = NULL;
           lca.be = be;
           lca.conn = conn;
           ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );
           rc = avl_apply( lc->lc_lai.lai_tree, ldap_chain_conn_apply,
                   (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE;
           ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );
         be->be_private = private;          be->be_private = private;
   
         return rc;          return rc;
Line 1303  chain_init( void ) Line 1572  chain_init( void )
   
         ldapchain.on_bi.bi_type = "chain";          ldapchain.on_bi.bi_type = "chain";
         ldapchain.on_bi.bi_db_init = ldap_chain_db_init;          ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
         ldapchain.on_bi.bi_db_open = ldap_chain_db_open;  
         ldapchain.on_bi.bi_db_config = ldap_chain_db_config;          ldapchain.on_bi.bi_db_config = ldap_chain_db_config;
           ldapchain.on_bi.bi_db_open = ldap_chain_db_open;
           ldapchain.on_bi.bi_db_close = ldap_chain_db_close;
         ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy;          ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy;
   
         /* ... otherwise the underlying backend's function would be called,          /* ... otherwise the underlying backend's function would be called,

Removed from v.1.34  
changed lines
  Added in v.1.35


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org