Diff for /servers/slapd/overlays/dynlist.c between versions 1.5.2.4 and 1.5.2.5

version 1.5.2.4, 2005/11/26 23:54:51 version 1.5.2.5, 2005/12/20 19:00:00
Line 22 Line 22
   
 #ifdef SLAPD_OVER_DYNLIST  #ifdef SLAPD_OVER_DYNLIST
   
   #if LDAP_VENDOR_VERSION_MINOR != X && LDAP_VENDOR_VERSION_MINOR < 3
   #define OL_2_2_COMPAT
   #elif defined(LDAP_DEVEL) && SLAPD_OVER_DYNGROUP != SLAPD_MOD_STATIC
   #define TAKEOVER_DYNGROUP
   #endif
   
 #include <stdio.h>  #include <stdio.h>
   
 #include <ac/string.h>  #include <ac/string.h>
   
 #include "slap.h"  #include "slap.h"
   #ifndef OL_2_2_COMPAT
   #include "config.h"
   #endif
 #include "lutil.h"  #include "lutil.h"
   
 /* FIXME: the code differs if SLAP_OPATTRS is defined or not;  /* FIXME: the code differs if SLAP_OPATTRS is defined or not;
Line 35 Line 44
 /* FIXME: slap_anlist_no_attrs was introduced in 2.3; here it  /* FIXME: slap_anlist_no_attrs was introduced in 2.3; here it
  * is anticipated to allow using this overlay with 2.2. */   * is anticipated to allow using this overlay with 2.2. */
   
 #if LDAP_VENDOR_VERSION_MINOR != X && LDAP_VENDOR_VERSION_MINOR < 3  #ifdef OL_2_2_COMPAT
 static AttributeName anlist_no_attrs[] = {  static AttributeName anlist_no_attrs[] = {
         { BER_BVC( LDAP_NO_ATTRS ), NULL, 0, NULL },          { BER_BVC( LDAP_NO_ATTRS ), NULL, 0, NULL },
         { BER_BVNULL, NULL, 0, NULL }          { BER_BVNULL, NULL, 0, NULL }
Line 44  static AttributeName anlist_no_attrs[] = Line 53  static AttributeName anlist_no_attrs[] =
 static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;  static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;
 #endif  #endif
   
 typedef struct dynlist_info {  typedef struct dynlist_info_t {
         ObjectClass             *dli_oc;          ObjectClass             *dli_oc;
         AttributeDescription    *dli_ad;          AttributeDescription    *dli_ad;
         AttributeDescription    *dli_member_ad;          AttributeDescription    *dli_member_ad;
         struct berval           dli_default_filter;          struct berval           dli_default_filter;
 } dynlist_info;          struct dynlist_info_t   *dli_next;
   } dynlist_info_t;
   
 static int  static dynlist_info_t *
 dynlist_is_dynlist( Operation *op, SlapReply *rs )  dynlist_is_dynlist( Operation *op, SlapReply *rs )
 {  {
         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;          slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;          dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
   
         Attribute       *a;          Attribute       *a;
   
Line 64  dynlist_is_dynlist( Operation *op, SlapR Line 74  dynlist_is_dynlist( Operation *op, SlapR
                 /* FIXME: objectClass must be present; for non-storage                  /* FIXME: objectClass must be present; for non-storage
                  * backends, like back-ldap, it needs to be added                   * backends, like back-ldap, it needs to be added
                  * to the requested attributes */                   * to the requested attributes */
                 return 0;                  return NULL;
         }          }
   
         if ( value_find_ex( slap_schema.si_ad_objectClass,           for ( ; dli; dli = dli->dli_next ) {
                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |                  if ( value_find_ex( slap_schema.si_ad_objectClass, 
                         SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,                                  SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                         a->a_nvals, &dli->dli_oc->soc_cname,                                  SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
                         op->o_tmpmemctx ) == 0 )                                  a->a_nvals, &dli->dli_oc->soc_cname,
         {                                  op->o_tmpmemctx ) == 0 )
                 return 1;                  {
                           return dli;
                   }
         }          }
   
         return 0;          return NULL;
 }  }
   
 static int  static int
 dynlist_make_filter( Operation *op, struct berval *oldf, struct berval *newf )  dynlist_make_filter( Operation *op, struct berval *oldf, struct berval *newf )
 {  {
         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;          slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;          dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
   
         char            *ptr;          char            *ptr;
   
Line 109  dynlist_make_filter( Operation *op, stru Line 121  dynlist_make_filter( Operation *op, stru
 }  }
   
 typedef struct dynlist_sc_t {  typedef struct dynlist_sc_t {
         dynlist_info    *dlc_dli;          dynlist_info_t    *dlc_dli;
         Entry           *dlc_e;          Entry           *dlc_e;
 } dynlist_sc_t;  } dynlist_sc_t;
   
Line 278  done:; Line 290  done:;
 }  }
                   
 static int  static int
 dynlist_send_entry( Operation *op, SlapReply *rs )  dynlist_send_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
 {  {
         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;  
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;  
   
         Attribute       *a;          Attribute       *a;
         slap_callback   cb;          slap_callback   cb;
         Operation       o = *op;          Operation       o = *op;
Line 367  dynlist_send_entry( Operation *op, SlapR Line 376  dynlist_send_entry( Operation *op, SlapR
                 o.ors_scope = lud->lud_scope;                  o.ors_scope = lud->lud_scope;
   
                 if ( dli->dli_member_ad != NULL ) {                  if ( dli->dli_member_ad != NULL ) {
                           /* if ( lud->lud_attrs != NULL ),
                            * the URL should be ignored */
                         o.ors_attrs = slap_anlist_no_attrs;                          o.ors_attrs = slap_anlist_no_attrs;
   
                 } else if ( lud->lud_attrs == NULL ) {                  } else if ( lud->lud_attrs == NULL ) {
Line 493  static int Line 504  static int
 dynlist_compare( Operation *op, SlapReply *rs )  dynlist_compare( Operation *op, SlapReply *rs )
 {  {
         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;          slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;          dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
   
         Attribute       *a;          for ( ; dli != NULL; dli = dli->dli_next ) {
         slap_callback   cb;                  if ( op->oq_compare.rs_ava->aa_desc == dli->dli_member_ad ) {
         Operation       o = *op;                          /* This compare is for one of the attributes we're
         SlapReply       r = { REP_SEARCH };                           * interested in. We'll use slapd's existing dyngroup
         AttributeName   an[2];                           * evaluator to get the answer we want.
         int             rc;                           */
         dynlist_sc_t    dlc = { 0 };                          int cache = op->o_do_not_cache;
                                   
                           op->o_do_not_cache = 1;
                           rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
                                   &op->oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
                           op->o_do_not_cache = cache;
                           switch ( rs->sr_err ) {
                           case LDAP_SUCCESS:
                                   rs->sr_err = LDAP_COMPARE_TRUE;
                                   break;
   
                           case LDAP_NO_SUCH_OBJECT:
                                   /* NOTE: backend_group() returns noSuchObject
                                    * if op_ndn does not exist; however, since
                                    * dynamic list expansion means that the
                                    * member attribute is virtually present, the
                                    * non-existence of the asserted value implies
                                    * the assertion is FALSE rather than
                                    * UNDEFINED */
                                   rs->sr_err = LDAP_COMPARE_FALSE;
                                   break;
                           }
   
         dlc.dlc_dli = dli;                          return SLAP_CB_CONTINUE;
         cb.sc_private = &dlc;                  }
         cb.sc_response = dynlist_sc_save_entry;          }
         cb.sc_cleanup = NULL;  
         cb.sc_next = NULL;  
         o.o_callback = &cb;  
   
         o.o_tag = LDAP_REQ_SEARCH;          dli = (dynlist_info_t *)on->on_bi.bi_private;
         o.ors_limit = NULL;          for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) {
         o.ors_tlimit = SLAP_NO_LIMIT;                  Attribute       *a;
         o.ors_slimit = SLAP_NO_LIMIT;                  slap_callback   cb;
                   Operation       o = *op;
                   SlapReply       r = { REP_SEARCH };
                   AttributeName   an[2];
                   int             rc;
                   dynlist_sc_t    dlc = { 0 };
                   Entry           *e;
   
         o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );                  int cache = op->o_do_not_cache;
         if ( !o.o_bd || !o.o_bd->be_search ) {                  struct berval   op_dn = op->o_dn,
                 return SLAP_CB_CONTINUE;                                  op_ndn = op->o_ndn;
         }                  BackendDB       *op_bd = op->o_bd;
   
                   /* fetch the entry as rootdn (a hack to see if it exists
                    * and if it has the right objectClass) */
                   op->o_do_not_cache = 1;
                   op->o_dn = op->o_bd->be_rootdn;
                   op->o_ndn = op->o_bd->be_rootndn;
                   op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
   
                   r.sr_err = be_entry_get_rw( op, &op->o_req_ndn,
                           dli->dli_oc, NULL, 0, &e );
                   if ( e != NULL ) {
                           be_entry_release_r( op, e );
                   }
                   op->o_do_not_cache = cache;
                   op->o_dn = op_dn;
                   op->o_ndn = op_ndn;
                   op->o_bd = op_bd;
                   if ( r.sr_err != LDAP_SUCCESS ) {
                           continue;
                   }
   
         BER_BVSTR( &o.ors_filterstr, "(objectClass=*)" );                  /* if the entry has the right objectClass, generate
         o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );                   * the dynamic list and compare */
         if ( o.ors_filter == NULL ) {                  dlc.dlc_dli = dli;
                 /* FIXME: error? */                  cb.sc_private = &dlc;
                 return SLAP_CB_CONTINUE;                  cb.sc_response = dynlist_sc_save_entry;
         }                  cb.sc_cleanup = NULL;
                   cb.sc_next = NULL;
                   o.o_callback = &cb;
   
                   o.o_tag = LDAP_REQ_SEARCH;
                   o.ors_limit = NULL;
                   o.ors_tlimit = SLAP_NO_LIMIT;
                   o.ors_slimit = SLAP_NO_LIMIT;
   
         o.ors_scope = LDAP_SCOPE_BASE;                  o.o_bd = select_backend( &o.o_req_ndn, 0, 1 );
         o.ors_deref = LDAP_DEREF_NEVER;                  if ( !o.o_bd || !o.o_bd->be_search ) {
         an[0].an_name = op->orc_ava->aa_desc->ad_cname;                          return SLAP_CB_CONTINUE;
         an[0].an_desc = op->orc_ava->aa_desc;                  }
         BER_BVZERO( &an[1].an_name );  
         o.ors_attrs = an;  
         o.ors_attrsonly = 0;  
   
         rc = o.o_bd->be_search( &o, &r );                  BER_BVSTR( &o.ors_filterstr, "(objectClass=*)" );
         filter_free_x( &o, o.ors_filter );                  o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );
                   if ( o.ors_filter == NULL ) {
                           /* FIXME: error? */
                           return SLAP_CB_CONTINUE;
                   }
   
         if ( rc != 0 ) {                  o.ors_scope = LDAP_SCOPE_BASE;
                 return rc;                  o.ors_deref = LDAP_DEREF_NEVER;
         }                  an[0].an_name = op->orc_ava->aa_desc->ad_cname;
                   an[0].an_desc = op->orc_ava->aa_desc;
                   BER_BVZERO( &an[1].an_name );
                   o.ors_attrs = an;
                   o.ors_attrsonly = 0;
   
         if ( dlc.dlc_e != NULL ) {                  rc = o.o_bd->be_search( &o, &r );
                 r.sr_entry = dlc.dlc_e;                  filter_free_x( &o, o.ors_filter );
         }  
   
         if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) {                  if ( rc != 0 ) {
                 /* error? */                          return rc;
                 return SLAP_CB_CONTINUE;                  }
         }  
   
         /* if we're here, we got a match... */                  if ( dlc.dlc_e != NULL ) {
         rs->sr_err = LDAP_COMPARE_FALSE;                          r.sr_entry = dlc.dlc_e;
         for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc );                  }
                 a != NULL;  
                 a = attrs_find( a->a_next, op->orc_ava->aa_desc ) )                  if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) {
         {                          /* error? */
                 if ( value_find_ex( op->orc_ava->aa_desc,                          return SLAP_CB_CONTINUE;
                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |                  }
                                 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,  
                         a->a_nvals, &op->orc_ava->aa_value, op->o_tmpmemctx ) == 0 )                  for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc );
                           a != NULL;
                           a = attrs_find( a->a_next, op->orc_ava->aa_desc ) )
                 {                  {
                         rs->sr_err = LDAP_COMPARE_TRUE;                          /* if we're here, we got a match... */
                         break;                          rs->sr_err = LDAP_COMPARE_FALSE;
   
                           if ( value_find_ex( op->orc_ava->aa_desc,
                                   SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                           SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
                                   a->a_nvals, &op->orc_ava->aa_value, op->o_tmpmemctx ) == 0 )
                           {
                                   rs->sr_err = LDAP_COMPARE_TRUE;
                                   break;
                           }
                 }                  }
         }  
   
         if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) {                  if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) {
                 entry_free( r.sr_entry );                          entry_free( r.sr_entry );
                   }
         }          }
   
         return SLAP_CB_CONTINUE;          return SLAP_CB_CONTINUE;
Line 577  dynlist_compare( Operation *op, SlapRepl Line 653  dynlist_compare( Operation *op, SlapRepl
 static int  static int
 dynlist_response( Operation *op, SlapReply *rs )  dynlist_response( Operation *op, SlapReply *rs )
 {  {
           dynlist_info_t  *dli;
   
         switch ( op->o_tag ) {          switch ( op->o_tag ) {
         case LDAP_REQ_SEARCH:          case LDAP_REQ_SEARCH:
                 if ( rs->sr_type == REP_SEARCH && !get_manageDSAit( op ) )                  if ( rs->sr_type == REP_SEARCH && !get_manageDSAit( op ) )
                 {                  {
                         if ( dynlist_is_dynlist( op, rs ) ) {                          dli = dynlist_is_dynlist( op, rs );
                                 return dynlist_send_entry( op, rs );                          if ( dli != NULL ) {
                                   return dynlist_send_entry( op, rs, dli );
                         }                          }
                 }                  }
                 break;                  break;
Line 611  dynlist_response( Operation *op, SlapRep Line 690  dynlist_response( Operation *op, SlapRep
 }  }
   
 static int  static int
   dynlist_build_def_filter( dynlist_info_t *dli )
   {
           char    *ptr;
   
           dli->dli_default_filter.bv_len = STRLENOF( "(!(objectClass=" "))" )
                   + dli->dli_oc->soc_cname.bv_len;
           dli->dli_default_filter.bv_val = SLAP_MALLOC( dli->dli_default_filter.bv_len + 1 );
           if ( dli->dli_default_filter.bv_val == NULL ) {
                   Debug( LDAP_DEBUG_ANY, "dynlist_db_open: malloc failed.\n",
                           0, 0, 0 );
                   return -1;
           }
   
           ptr = lutil_strcopy( dli->dli_default_filter.bv_val, "(!(objectClass=" );
           ptr = lutil_strcopy( ptr, dli->dli_oc->soc_cname.bv_val );
           ptr = lutil_strcopy( ptr, "))" );
   
           assert( dli->dli_default_filter.bv_len == ptr - dli->dli_default_filter.bv_val );
   
           return 0;
   }
   
   #ifdef OL_2_2_COMPAT
   static int
 dynlist_db_config(  dynlist_db_config(
         BackendDB       *be,          BackendDB       *be,
         const char      *fname,          const char      *fname,
Line 619  dynlist_db_config( Line 722  dynlist_db_config(
         char            **argv )          char            **argv )
 {  {
         slap_overinst   *on = (slap_overinst *)be->bd_info;          slap_overinst   *on = (slap_overinst *)be->bd_info;
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;  
   
         int             rc = 0;          int             rc = 0;
   
         if ( strcasecmp( argv[0], "dynlist-oc" ) == 0 ) {          if ( strcasecmp( argv[0], "dynlist-attrset" ) == 0 ) {
                 if ( argc != 2 ) {                  dynlist_info_t          **dlip;
                         fprintf( stderr, "dynlist-oc <oc>\n" );                  ObjectClass             *oc;
                   AttributeDescription    *ad = NULL,
                                           *member_ad = NULL;
                   const char              *text;
   
                   if ( argc < 3 || argc > 4 ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "invalid arg number #%d.\n",
                                   fname, lineno, argc );
                         return 1;                          return 1;
                 }                  }
                 dli->dli_oc = oc_find( argv[1] );  
                 if ( dli->dli_oc == NULL ) {                  oc = oc_find( argv[1] );
                         fprintf( stderr, "dynlist-oc <oc>: "                  if ( oc == NULL ) {
                                         "unable to find ObjectClass "                          Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                         "\"%s\"\n", argv[1] );                                  "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "unable to find ObjectClass \"%s\"\n",
                                   fname, lineno, argv[ 1 ] );
                         return 1;                          return 1;
                 }                  }
   
         } else if ( strcasecmp( argv[0], "dynlist-ad" ) == 0 ) {                  rc = slap_str2ad( argv[2], &ad, &text );
                 const char      *text;                  if ( rc != LDAP_SUCCESS ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "unable to find AttributeDescription \"%s\"\n",
                                   fname, lineno, argv[2] );
                           return 1;
                   }
   
                 if ( argc != 2 ) {                  if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
                         fprintf( stderr, "dynlist-ad <ad>\n" );                          Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "AttributeDescription \"%s\" "
                                   "must be a subtype of \"labeledURI\"\n",
                                   fname, lineno, argv[2] );
                         return 1;                          return 1;
                 }                  }
                 dli->dli_ad = NULL;  
                 rc = slap_str2ad( argv[1], &dli->dli_ad, &text );                  if ( argc == 4 ) {
                 if ( rc != LDAP_SUCCESS ) {                          rc = slap_str2ad( argv[3], &member_ad, &text );
                         fprintf( stderr, "dynlist-ad <ad>: "                          if ( rc != LDAP_SUCCESS ) {
                                         "unable to find AttributeDescription "                                  Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                         "\"%s\"\n", argv[1] );                                          "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "unable to find AttributeDescription \"%s\"\n",
                                           fname, lineno, argv[3] );
                                   return 1;
                           }
                   }
   
                   for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                           *dlip; dlip = &(*dlip)->dli_next )
                   {
                           /* The check on objectClass may be relaxed */
   #if 0
                           if ( (*dlip)->dli_oc == oc ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "objectClass \"%s\" already mapped.\n",
                                           fname, lineno, oc->soc_cname.bv_val );
                                   return 1;
                           }
   #endif
   
                           if ( (*dlip)->dli_ad == ad ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "URL attributeDescription \"%s\" already mapped.\n",
                                           fname, lineno, ad->ad_cname.bv_val );
                                   return 1;
                           }
   
                           if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "member attributeDescription \"%s\" already mapped.\n",
                                           fname, lineno, member_ad->ad_cname.bv_val );
                                   return 1;
                           }
                   }
   
                   *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
                   (*dlip)->dli_oc = oc;
                   (*dlip)->dli_ad = ad;
                   (*dlip)->dli_member_ad = member_ad;
   
                   if ( dynlist_build_def_filter( *dlip ) ) {
                           ch_free( *dlip );
                           *dlip = NULL;
                         return 1;                          return 1;
                 }                  }
   
         } else if ( strcasecmp( argv[0], "dynlist-member-ad" ) == 0 ) {          /* allow dyngroup syntax */
                 const char      *text;          } else if ( strcasecmp( argv[0], "dynlist-attrpair" ) == 0 ) {
                   dynlist_info_t          **dlip;
                   ObjectClass             *oc;
                   AttributeDescription    *ad = NULL,
                                           *member_ad = NULL;
                   const char              *text;
   
                   if ( argc != 3 ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "invalid arg number #%d.\n",
                                   fname, lineno, argc );
                           return 1;
                   }
   
                 if ( argc != 2 ) {                  oc = oc_find( "groupOfURLs" );
                         fprintf( stderr, "dynlist-member-ad <ad>\n" );                  if ( oc == NULL ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "unable to find default ObjectClass \"groupOfURLs\"\n",
                                   fname, lineno, 0 );
                         return 1;                          return 1;
                 }                  }
                 dli->dli_member_ad = NULL;  
                 rc = slap_str2ad( argv[1], &dli->dli_member_ad, &text );                  rc = slap_str2ad( argv[1], &member_ad, &text );
                 if ( rc != LDAP_SUCCESS ) {                  if ( rc != LDAP_SUCCESS ) {
                         fprintf( stderr, "dynlist-member-ad <ad>: "                          Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                         "unable to find AttributeDescription "                                  "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                         "\"%s\"\n", argv[1] );                                  "unable to find AttributeDescription \"%s\"\n",
                                   fname, lineno, argv[1] );
                           return 1;
                   }
   
                   rc = slap_str2ad( argv[2], &ad, &text );
                   if ( rc != LDAP_SUCCESS ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "unable to find AttributeDescription \"%s\"\n",
                                   fname, lineno, argv[2] );
                           return 1;
                   }
   
                   if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
                           Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "AttributeDescription \"%s\" "
                                   "must be a subtype of \"labeledURI\"\n",
                                   fname, lineno, argv[2] );
                           return 1;
                   }
   
   
                   for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                           *dlip; dlip = &(*dlip)->dli_next )
                   {
   #if 0
                           /* The check on objectClass may be relaxed */
                           if ( (*dlip)->dli_oc == oc ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "objectClass \"%s\" already mapped.\n",
                                           fname, lineno, oc->soc_cname.bv_val );
                                   return 1;
                           }
   #endif
   
                           if ( (*dlip)->dli_ad == ad ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "URL attributeDescription \"%s\" already mapped.\n",
                                           fname, lineno, ad->ad_cname.bv_val );
                                   return 1;
                           }
   
                           if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
                                   Debug( LDAP_DEBUG_ANY, "%s: line %d: "
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "member attributeDescription \"%s\" already mapped.\n",
                                           fname, lineno, member_ad->ad_cname.bv_val );
                                   return 1;
                           }
                   }
   
                   *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
                   (*dlip)->dli_oc = oc;
                   (*dlip)->dli_ad = ad;
                   (*dlip)->dli_member_ad = member_ad;
   
                   if ( dynlist_build_def_filter( *dlip ) ) {
                           ch_free( *dlip );
                           *dlip = NULL;
                         return 1;                          return 1;
                 }                  }
   
Line 675  dynlist_db_config( Line 922  dynlist_db_config(
         return rc;          return rc;
 }  }
   
   #else
   enum {
           DL_ATTRSET = 1,
           DL_ATTRPAIR,
           DL_ATTRPAIR_COMPAT,
           DL_LAST
   };
   
   static ConfigDriver     dl_cfgen;
   
   static ConfigTable dlcfg[] = {
           { "dynlist-attrset", "group-oc> <URL-ad> <member-ad",
                   3, 4, 0, ARG_MAGIC|DL_ATTRSET, dl_cfgen,
                   "( OLcfgOvAt:8.1 NAME 'olcDLattrSet' "
                           "DESC 'Dynamic list: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
                           "EQUALITY caseIgnoreMatch "
                           "SYNTAX OMsDirectoryString "
                           "X-ORDERED 'VALUES' )",
                           NULL, NULL },
           { "dynlist-attrpair", "member-ad> <URL-ad",
                   3, 3, 0, ARG_MAGIC|DL_ATTRPAIR, dl_cfgen,
                           NULL, NULL, NULL },
   #ifdef TAKEOVER_DYNGROUP
           { "attrpair", "member-ad> <URL-ad",
                   3, 3, 0, ARG_MAGIC|DL_ATTRPAIR_COMPAT, dl_cfgen,
                           NULL, NULL, NULL },
   #endif
           { NULL, NULL, 0, 0, 0, ARG_IGNORED }
   };
   
   static ConfigOCs dlocs[] = {
           { "( OLcfgOvOc:8.1 "
                   "NAME 'olcDynamicList' "
                   "DESC 'Dynamic list configuration' "
                   "SUP olcOverlayConfig "
                   "MAY olcDLattrSet )",
                   Cft_Overlay, dlcfg, NULL, NULL },
           { NULL, 0, NULL }
   };
   
 static int  static int
 dynlist_db_init(  dl_cfgen( ConfigArgs *c )
         BackendDB       *be )  
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          slap_overinst   *on = (slap_overinst *)c->bi;
         dynlist_info    *dli;          dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private;
   
         dli = (dynlist_info *)ch_malloc( sizeof( dynlist_info ) );          int             rc = 0, i;
         memset( dli, 0, sizeof( dynlist_info ) );  
   
         on->on_bi.bi_private = (void *)dli;          if ( c->op == SLAP_CONFIG_EMIT ) {
                   switch( c->type ) {
                   case DL_ATTRSET:
                           for ( i = 0; dli; i++, dli = dli->dli_next ) {
                                   struct berval   bv;
                                   char            *ptr = c->msg;
   
                                   assert( dli->dli_oc != NULL );
                                   assert( dli->dli_ad != NULL );
   
                                   ptr += snprintf( c->msg, sizeof( c->msg ),
                                           SLAP_X_ORDERED_FMT "%s %s", i,
                                           dli->dli_oc->soc_cname.bv_val,
                                           dli->dli_ad->ad_cname.bv_val );
   
                                   if ( dli->dli_member_ad != NULL ) {
                                           ptr[ 0 ] = ' ';
                                           ptr++;
                                           ptr = lutil_strcopy( ptr, dli->dli_member_ad->ad_cname.bv_val );
                                   }
   
         return 0;                                  bv.bv_val = c->msg;
                                   bv.bv_len = ptr - bv.bv_val;
                                   value_add_one( &c->rvalue_vals, &bv );
                           }
                           break;
   
                   case DL_ATTRPAIR_COMPAT:
                   case DL_ATTRPAIR:
                           rc = 1;
                           break;
   
                   default:
                           rc = 1;
                           break;
                   }
   
                   return rc;
   
           } else if ( c->op == LDAP_MOD_DELETE ) {
                   switch( c->type ) {
                   case DL_ATTRSET:
                           if ( c->valx < 0 ) {
                                   dynlist_info_t  *dli_next;
   
                                   for ( dli_next = dli; dli_next; dli = dli_next ) {
                                           dli_next = dli->dli_next;
   
                                           ch_free( dli->dli_default_filter.bv_val );
                                           ch_free( dli );
                                   }
   
                                   on->on_bi.bi_private = NULL;
   
                           } else {
                                   dynlist_info_t  **dlip;
   
                                   for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                                           i < c->valx; i++ )
                                   {
                                           if ( *dlip == NULL ) {
                                                   return 1;
                                           }
                                           dlip = &(*dlip)->dli_next;
                                   }
   
                                   dli = *dlip;
                                   *dlip = dli->dli_next;
                                   ch_free( dli->dli_default_filter.bv_val );
                                   ch_free( dli );
   
                                   dli = (dynlist_info_t *)on->on_bi.bi_private;
                           }
                           break;
   
                   case DL_ATTRPAIR_COMPAT:
                   case DL_ATTRPAIR:
                           rc = 1;
                           break;
   
                   default:
                           rc = 1;
                           break;
                   }
   
                   return 1;       /* FIXME */
           }
   
           switch( c->type ) {
           case DL_ATTRSET: {
                   dynlist_info_t          **dlip,
                                           *dli_next = NULL;
                   ObjectClass             *oc = NULL;
                   AttributeDescription    *ad = NULL,
                                           *member_ad = NULL;
                   const char              *text;
   
                   oc = oc_find( c->argv[ 1 ] );
                   if ( oc == NULL ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "unable to find ObjectClass \"%s\"",
                                   c->argv[ 1 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
                   if ( rc != LDAP_SUCCESS ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "unable to find AttributeDescription \"%s\"",
                                   c->argv[ 2 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "AttributeDescription \"%s\" "
                                   "must be a subtype of \"labeledURI\"",
                                   c->argv[ 2 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   if ( c->argc == 4 ) {
                           rc = slap_str2ad( c->argv[ 3 ], &member_ad, &text );
                           if ( rc != LDAP_SUCCESS ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "unable to find AttributeDescription \"%s\"\n",
                                           c->argv[ 3 ] );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
                   }
   
                   for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                           *dlip; dlip = &(*dlip)->dli_next )
                   {
                           /* The check on objectClass may be relaxed */
   #if 0
                           if ( (*dlip)->dli_oc == oc ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "objectClass \"%s\" already mapped.\n",
                                           oc->soc_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
   #endif
   
                           if ( (*dlip)->dli_ad == ad ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "URL attributeDescription \"%s\" already mapped.\n",
                                           ad->ad_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
   
                           if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                           "member attributeDescription \"%s\" already mapped.\n",
                                           member_ad->ad_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
                   }
   
                   if ( c->valx > 0 ) {
                           int     i;
   
                           for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                                   i < c->valx; i++ )
                           {
                                   if ( *dlip == NULL ) {
                                           snprintf( c->msg, sizeof( c->msg ),
                                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                                   "invalid index {%d}\n",
                                                   c->valx );
                                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                                   c->log, c->msg, 0 );
                                           return 1;
                                   }
                                   dlip = &(*dlip)->dli_next;
                           }
                           dli_next = *dlip;
   
                   } else {
                           for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                                   *dlip; dlip = &(*dlip)->dli_next )
                                   /* goto last */;
                   }
   
                   *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
   
                   (*dlip)->dli_oc = oc;
                   (*dlip)->dli_ad = ad;
                   (*dlip)->dli_member_ad = member_ad;
                   (*dlip)->dli_next = dli_next;
   
                   rc = dynlist_build_def_filter( *dlip );
   
                   } break;
   
           case DL_ATTRPAIR_COMPAT:
                   snprintf( c->msg, sizeof( c->msg ),
                           "warning: \"attrpair\" only supported for limited "
                           "backward compatibility with overlay \"dyngroup\"" );
                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                   /* fallthru */
   
           case DL_ATTRPAIR: {
                   dynlist_info_t          **dlip;
                   ObjectClass             *oc = NULL;
                   AttributeDescription    *ad = NULL,
                                           *member_ad = NULL;
                   const char              *text;
   
                   oc = oc_find( "groupOfURLs" );
                   if ( oc == NULL ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "unable to find default ObjectClass \"groupOfURLs\"" );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text );
                   if ( rc != LDAP_SUCCESS ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "unable to find AttributeDescription \"%s\"",
                                   c->argv[ 1 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
                   if ( rc != LDAP_SUCCESS ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                   "unable to find AttributeDescription \"%s\"\n",
                                   c->argv[ 2 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
                           snprintf( c->msg, sizeof( c->msg ),
                                   "\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
                                   "AttributeDescription \"%s\" "
                                   "must be a subtype of \"labeledURI\"",
                                   c->argv[ 2 ] );
                           Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                   c->log, c->msg, 0 );
                           return 1;
                   }
   
                   for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
                           *dlip; dlip = &(*dlip)->dli_next )
                   {
                           /* The check on objectClass may be relaxed */
   #if 0
                           if ( (*dlip)->dli_oc == oc ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "objectClass \"%s\" already mapped.\n",
                                           oc->soc_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
   #endif
   
                           if ( (*dlip)->dli_ad == ad ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "URL attributeDescription \"%s\" already mapped.\n",
                                           ad->ad_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
   
                           if ( member_ad != NULL && (*dlip)->dli_member_ad == member_ad ) {
                                   snprintf( c->msg, sizeof( c->msg ),
                                           "\"dynlist-attrpair <member-ad> <URL-ad>\": "
                                           "member attributeDescription \"%s\" already mapped.\n",
                                           member_ad->ad_cname.bv_val );
                                   Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
                                           c->log, c->msg, 0 );
                                   return 1;
                           }
                   }
   
                   *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
   
                   (*dlip)->dli_oc = oc;
                   (*dlip)->dli_ad = ad;
                   (*dlip)->dli_member_ad = member_ad;
   
                   rc = dynlist_build_def_filter( *dlip );
   
                   } break;
   
           default:
                   rc = 1;
                   break;
           }
   
           return rc;
 }  }
   #endif
   
 static int  static int
 dynlist_db_open(  dynlist_db_open(
         BackendDB       *be )          BackendDB       *be )
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          slap_overinst           *on = (slap_overinst *) be->bd_info;
         dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;          dynlist_info_t          *dli = (dynlist_info_t *)on->on_bi.bi_private;
         ber_len_t       len;          ObjectClass             *oc = NULL;
         char            *ptr;          AttributeDescription    *ad = NULL;
   
         if ( dli->dli_oc == NULL ) {          if ( dli == NULL ) {
                 fprintf( stderr, "dynlist_db_open(): missing \"dynlist-oc <ObjectClass>\"\n" );                  dli = ch_calloc( 1, sizeof( dynlist_info_t ) );
                 return -1;                  on->on_bi.bi_private = (void *)dli;
         }          }
   
         if ( dli->dli_ad == NULL ) {          for ( ; dli; dli = dli->dli_next ) {
                 fprintf( stderr, "dynlist_db_open(): missing \"dynlist-ad <AttributeDescription>\"\n" );                  const char      *text;
                 return -1;                  int             rc;
         }  
   
         len = STRLENOF( "(!(objectClass=" "))" )                  if ( dli->dli_oc == NULL ) {
                 + dli->dli_oc->soc_cname.bv_len;                          if ( oc == NULL ) {
         dli->dli_default_filter.bv_val = SLAP_MALLOC( len + 1 );                                  oc = oc_find( "groupOfURLs" );
         if ( dli->dli_default_filter.bv_val == NULL ) {                                  if ( oc == NULL ) {
                 fprintf( stderr, "dynlist_db_open(): malloc failed\n" );                                          Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
                 return -1;                                                  "unable to fetch objectClass \"groupOfURLs\".\n",
                                                   0, 0, 0 );
                                           return 1;
                                   }
                           }
   
                           dli->dli_oc = oc;
                   }
   
                   if ( dli->dli_ad == NULL ) {
                           if ( ad == NULL ) {
                                   rc = slap_str2ad( "memberURL", &ad, &text );
                                   if ( rc != LDAP_SUCCESS ) {
                                           Debug( LDAP_DEBUG_ANY, "dynlist_db_open: "
                                                   "unable to fetch attributeDescription \"memberURL\": %d (%s).\n",
                                                   rc, text, 0 );
                                           return 1;
                                   }
                           }
                   
                           dli->dli_ad = ad;                       
                   }
   
                   rc = dynlist_build_def_filter( dli );
                   if ( rc != 0 ) {
                           return rc;
                   }
         }          }
         ptr = lutil_strcopy( dli->dli_default_filter.bv_val, "(!(objectClass=" );  
         ptr = lutil_strcopy( ptr, dli->dli_oc->soc_cname.bv_val );  
         ptr = lutil_strcopy( ptr, "))" );  
         dli->dli_default_filter.bv_len = ptr - dli->dli_default_filter.bv_val;  
   
         return 0;          return 0;
 }  }
Line 729  dynlist_db_destroy( Line 1359  dynlist_db_destroy(
         BackendDB       *be )          BackendDB       *be )
 {  {
         slap_overinst   *on = (slap_overinst *) be->bd_info;          slap_overinst   *on = (slap_overinst *) be->bd_info;
         int             rc = 0;  
   
         if ( on->on_bi.bi_private ) {          if ( on->on_bi.bi_private ) {
                 dynlist_info    *dli = (dynlist_info *)on->on_bi.bi_private;                  dynlist_info_t  *dli = (dynlist_info_t *)on->on_bi.bi_private,
                                   *dli_next;
   
                 dli->dli_oc = NULL;                  for ( dli_next = dli; dli_next; dli = dli_next ) {
                 dli->dli_ad = NULL;                          dli_next = dli->dli_next;
   
                 ch_free( dli );                          ch_free( dli->dli_default_filter.bv_val );
                           ch_free( dli );
                   }
         }          }
   
         return rc;          return 0;
 }  }
   
 static slap_overinst dynlist = { { NULL } };  static slap_overinst    dynlist = { { NULL } };
   #ifdef TAKEOVER_DYNGROUP
   static char             *obsolete_names[] = {
           "dyngroup",
           NULL
   };
   #endif
   
 #if SLAPD_OVER_DYNLIST == SLAPD_MOD_DYNAMIC  #if SLAPD_OVER_DYNLIST == SLAPD_MOD_DYNAMIC
 static  static
Line 751  static Line 1389  static
 int  int
 dynlist_initialize(void)  dynlist_initialize(void)
 {  {
   #ifndef OL_2_2_COMPAT
           int     rc = 0;
   #endif
   
         dynlist.on_bi.bi_type = "dynlist";          dynlist.on_bi.bi_type = "dynlist";
         dynlist.on_bi.bi_db_init = dynlist_db_init;  
   #ifdef TAKEOVER_DYNGROUP
           /* makes dynlist incompatible with dyngroup */
           dynlist.on_bi.bi_obsolete_names = obsolete_names;
   #endif
   
   #ifdef OL_2_2_COMPAT
         dynlist.on_bi.bi_db_config = dynlist_db_config;          dynlist.on_bi.bi_db_config = dynlist_db_config;
   #else
           dynlist.on_bi.bi_db_config = config_generic_wrapper;
   #endif
         dynlist.on_bi.bi_db_open = dynlist_db_open;          dynlist.on_bi.bi_db_open = dynlist_db_open;
         dynlist.on_bi.bi_db_destroy = dynlist_db_destroy;          dynlist.on_bi.bi_db_destroy = dynlist_db_destroy;
   
         dynlist.on_response = dynlist_response;          dynlist.on_response = dynlist_response;
   
   #ifndef OL_2_2_COMPAT
           dynlist.on_bi.bi_cf_ocs = dlocs;
   
           rc = config_register_schema( dlcfg, dlocs );
           if ( rc ) {
                   return rc;
           }
   #endif
   
         return overlay_register( &dynlist );          return overlay_register( &dynlist );
 }  }
   

Removed from v.1.5.2.4  
changed lines
  Added in v.1.5.2.5


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