]> git.sur5r.net Git - openldap/commitdiff
add global, per backend and per op_ndn time/size soft, hard and to-be-checked limits...
authorPierangelo Masarati <ando@openldap.org>
Wed, 1 Aug 2001 10:09:04 +0000 (10:09 +0000)
committerPierangelo Masarati <ando@openldap.org>
Wed, 1 Aug 2001 10:09:04 +0000 (10:09 +0000)
doc/man/man5/slapd.conf.5
servers/slapd/back-ldbm/search.c
servers/slapd/backend.c
servers/slapd/config.c
servers/slapd/limits.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/tools/mimic.c

index e6797abc35d73b9f06e8af79685a4f32c9a7a771..6a3841f9c62d711586615b37cd8ac007c532bec0 100644 (file)
@@ -158,7 +158,7 @@ feature.  The default is 0.
 Read additional configuration information from the given file before
 continuing with the next line of the current file.
 .TP
-.B limits [dn[.{exact|regex}]=]<pattern> <limit> [<limit> [...]]
+.B limits [dn[.{exact|regex}]=]<pattern> <limit> [...]
 Specify time and size limits based on the distinguished name that
 initiated an operation.
 The argument
@@ -169,14 +169,69 @@ It is a distinguished name in case of
 match, or an Extended Regex pattern in case of
 .BR regex
 match (the default).
+The currently supported limits are "size" and "time".
+
+The syntax for time limits is 
+.BR time[.{soft|hard}]=<integer> ,
+where 
+.BR integer
+is the number of seconds slapd will spend answering a search request.
+If no time limit is explicitly requested by the client, the 
+.BR soft
+limit is used; if the requested time limit exceedes the
+.BR hard
+limit, an "Unwilling to perform" is returned.
+If the
+.BR hard
+limit is set to zero, the soft limit is used in either case;
+if it is set to -1, no hard limit is enforced.
+Explicit requests for time limits smaller or equal to the
+.BR hard 
+limit are honored.
+If no flag is set, the value is assigned to the 
+.BR soft 
+limit, and the
+.BR hard
+limit is set to zero, to preserve the original behavior.
+
+The syntax for size limits is
+.BR size[.{soft|hard|unchecked}]=<integer> ,
+where
+.BR integer
+is the maximum number of entries slapd will return answering a search 
+request.
+If no size limit is explicitly requested by the client, the
+.BR soft
+limit is used; if the requested size limit exceedes the
+.BR hard
+limit, an "Unwilling to perform" is returned.
+If the 
+.BR hard
+limit is set to zero, the soft limit is used in either case;
+if it is set to -1, no hard limit is enforced.
+Explicit requests for size limits smaller or equal to the
+.BR hard
+limit are honored.
 The
-.BR limit
-argument(s) take the form
-.BR <name>=<value>
-where the currently supported names are "size" and "time", whose values
-are the maximum number of entries that are returned by a search
-and the number of seconds slapd will spend answering a search request.  
+.BR unchecked
+flag sets a limit on the number of candidates a search request is allowed
+to examine.
+If the selected candidates exceed the 
+.BR unchecked
+limit, the search will abort with "Unwilling to perform".
+If no flag is set, the value is assigned to the
+.BR soft 
+limit, and the
+.BR hard
+limit is set to zero, to preserve the original behavior.
+
 In case of no match, the global limits are used.
+The default values are the same of
+.BR sizelimit
+and
+.BR timelimit ;
+no limit is set on 
+.BR unchecked .
 This feature is currently exploited by the ldbm backend only.
 .TP
 .B loglevel <integer>
@@ -455,9 +510,15 @@ e.g. ldapi:// (and eventually IPSEC).  It is not normally used.
 .B schemacheck { on | off }
 Turn schema checking on or off. The default is on.
 .TP
-.B sizelimit <integer>
+.B sizelimit <integer> 
+.TP
+.B sizelimit size[.{soft|hard|unchecked}]=<integer>
 Specify the maximum number of entries to return from a search operation.
 The default size limit is 500.
+The second format allows a fine grain setting of the size limits.
+See
+.BR limits
+for an explanation of the different flags.
 .TP
 .B sockbuf_max_incoming <integer>
 Specify the maximum incoming LDAP PDU size for anonymous sessions.
@@ -477,9 +538,15 @@ Specify the maximum size of the primary thread pool.
 The default is 32.
 .TP
 .B timelimit <integer>
+.TP
+.B sizelimit size[.{soft|hard}]=<integer>
 Specify the maximum number of seconds (in real time)
 .B slapd
 will spend answering a search request.  The default time limit is 3600.
+The second format allows a fine grain setting of the time limits.
+See
+.BR limits
+for an explanation of the different flags.
 .SH TLS OPTIONS
 If
 .B slapd
index 6af3cf97c975b4a327987461e30929c55ba55903..b4a9a29fb3c25af0f55d539a3291e789912cb7b2 100644 (file)
@@ -53,7 +53,7 @@ ldbm_back_search(
        int             nentries = 0;
        int             manageDSAit = get_manageDSAit( op );
 
-       int timelimit = -1, sizelimit = -1;
+       struct slap_limits_set *limit = NULL;
        int isroot = 0;
                
 #ifdef NEW_LOGGING
@@ -184,28 +184,74 @@ searchit:
                goto done;
        }
 
+       /* if not root, get appropriate limits */
        if ( be_isroot( be, op->o_ndn ) ) {
                isroot = 1;
        } else {
-               if ( get_limits( be, op->o_ndn, &timelimit, &sizelimit) ) {
-                       timelimit = be->be_timelimit;
-                       sizelimit = be->be_sizelimit;
+               ( void ) get_limits( be, op->o_ndn, &limit );
+       }
+
+       /* if candidates exceed to-be-checked entries, abort */
+       if ( !isroot && limit->lms_s_unchecked != -1 ) {
+               if ( ID_BLOCK_NIDS( candidates ) > limit->lms_s_unchecked ) {
+                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL, 0 );
+                       rc = 0;
+                       goto done;
                }
        }
+       
+       /* if no time limit requested, use soft limit (unless root!) */
+       if ( tlimit <= 0 ) {
+               if ( isroot ) {
+                       tlimit = -1;    /* allow root to set no limit */
+               } else {
+                       tlimit = limit->lms_t_soft;
+               }
+               
+       /* if requested limit higher than hard limit, abort */
+       } else if ( tlimit > limit->lms_t_hard ) {
+               /* no hard limit means use soft instead */
+               if ( limit->lms_t_hard == 0 ) {
+                       tlimit = limit->lms_t_soft;
+                       
+               /* positive hard limit means abort */
+               } else if ( limit->lms_t_hard > 0 ) {
+                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL, 0 );
+                       rc = 0; 
+                       goto done;
+               }
 
-       if ( tlimit == 0 && isroot ) {
-               tlimit = -1;    /* allow root to set no limit */
-       } else {
-               tlimit = (tlimit > timelimit || tlimit < 1) ?
-                   timelimit : tlimit;
-               stoptime = op->o_time + tlimit;
+               /* negative hard limit means no limit */
        }
 
-       if ( slimit == 0 && isroot ) {
-               slimit = -1;    /* allow root to set no limit */
-       } else {
-               slimit = (slimit > sizelimit || slimit < 1) ?
-                   sizelimit : slimit;
+       /* compute it anyway; root does not use it */
+       stoptime = op->o_time + tlimit;
+
+       /* if no size limit requested, use soft limit (unless root!) */
+       if ( slimit == 0 ) {
+               if ( isroot ) {
+                       slimit = -1;    /* allow root to set no limit */
+               } else {
+                       slimit = limit->lms_s_soft;
+               }
+       
+       /* if requested limit higher than hard limit, abort */
+       } else if ( slimit > limit->lms_s_hard ) {
+               /* no hard limit means use soft instead */
+               if ( limit->lms_s_hard == 0 ) {
+                       slimit = limit->lms_s_soft;
+
+               /* positive hard limit means abort */
+               } else if ( limit->lms_s_hard > 0 ) {
+                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL, 0 );
+                       rc = 0;
+                       goto done;
+               }
+
+               /* negative hard limit means no limit */
        }
 
        for ( id = idl_firstid( candidates, &cursor ); id != NOID;
index fa749b85e90e85bf178e783884205e1d86b639e8..105e95b75cdf803408475df0b23cc30d9c4a2504 100644 (file)
@@ -469,8 +469,7 @@ backend_db_init(
        be = &backends[nbackends++];
 
        be->bd_info = bi;
-       be->be_sizelimit = defsize;
-       be->be_timelimit = deftime;
+       be->be_def_limit = deflimit;
        be->be_dfltaccess = global_default_access;
 
        be->be_restrictops = global_restrictops;
index ed3d49646fdbb858d837e945e1dff335c443632b..3547d7548d9e760fea32fc5e15ef3fdf0c0ed0cf 100644 (file)
 /*
  * defaults for various global variables
  */
-int            defsize = SLAPD_DEFAULT_SIZELIMIT;
-int            deftime = SLAPD_DEFAULT_TIMELIMIT;
+struct slap_limits_set deflimit = {
+       SLAPD_DEFAULT_TIMELIMIT,        /* backward compatible limits */
+       0,
+
+       SLAPD_DEFAULT_SIZELIMIT,        /* backward compatible limits */
+       0,
+       -1                              /* no limit on unchecked size */
+};
+
 AccessControl  *global_acl = NULL;
 slap_access_t          global_default_access = ACL_READ;
 slap_mask_t            global_restrictops = 0;
@@ -685,8 +692,11 @@ read_config( const char *fname )
                                return( 1 );
                        }
 
-               /* set time limit */
+               /* set size limit */
                } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
+                       int rc = 0;
+                       struct slap_limits_set *lim;
+                       
                        if ( cargc < 2 ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
@@ -700,14 +710,39 @@ read_config( const char *fname )
 
                                return( 1 );
                        }
+
                        if ( be == NULL ) {
-                               defsize = atoi( cargv[1] );
+                               lim = &deflimit;
                        } else {
-                               be->be_sizelimit = atoi( cargv[1] );
+                               lim = &be->be_def_limit;
+                       }
+
+                       if ( strncasecmp( cargv[1], "size", 4 ) == 0 ) {
+                               rc = parse_limit( cargv[1], lim );
+                       } else {
+                               lim->lms_s_soft = atoi( cargv[1] );
+                               lim->lms_s_hard = 0;
+                       }
+
+                       if ( rc ) {
+#ifdef NEW_LOGGING
+                               LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+                                          "%s: line %d: unable to parse value"
+                                          " \"%s\" in \"sizelimit <limit>\""
+                                          " line.\n",
+                                          fname, lineno, cargv[1] ));
+#else
+                               Debug( LDAP_DEBUG_ANY,
+           "%s: line %d: unable to parse value \"%s\" in \"sizelimit <limit>\" line\n",
+                                   fname, lineno, cargv[1] );
+#endif
                        }
 
                /* set time limit */
                } else if ( strcasecmp( cargv[0], "timelimit" ) == 0 ) {
+                       int rc = 0;
+                       struct slap_limits_set *lim;
+                       
                        if ( cargc < 2 ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
@@ -721,10 +756,32 @@ read_config( const char *fname )
 
                                return( 1 );
                        }
+                       
                        if ( be == NULL ) {
-                               deftime = atoi( cargv[1] );
+                               lim = &deflimit;
+                       } else {
+                               lim = &be->be_def_limit;
+                       }
+
+                       if ( strncasecmp( cargv[1], "time", 4 ) == 0 ) {
+                               rc = parse_limit( cargv[1], lim );
                        } else {
-                               be->be_timelimit = atoi( cargv[1] );
+                               lim->lms_t_soft = atoi( cargv[1] );
+                               lim->lms_t_hard = 0;
+                       }
+
+                       if ( rc ) {
+#ifdef NEW_LOGGING
+                               LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+                                          "%s: line %d: unable to parse value"
+                                          " \"%s\" in \"timelimit <limit>\""
+                                          " line.\n",
+                                          fname, lineno, cargv[1] ));
+#else
+                               Debug( LDAP_DEBUG_ANY,
+           "%s: line %d: unable to parse value \"%s\" in \"timelimit <limit>\" line\n",
+                                   fname, lineno, cargv[1] );
+#endif
                        }
 
                /* set regex-based limits */
index ef6ccc9da673c5364db60bdf523fe95e11ac9a20..5e27a2d8320297e5d2b5681487c326b4b75e71f2 100644 (file)
 
 int
 get_limits( 
-       Backend         *be, 
-       const char      *ndn, 
-       int             *timelimit, 
-       int             *sizelimit 
+       Backend                 *be, 
+       const char              *ndn, 
+       struct slap_limits_set  **limit
 )
 {
        struct slap_limits **lm;
 
        assert( be );
-       assert( timelimit );
-       assert( sizelimit );
+       assert( limit );
 
        /*
         * default values
         */
-       *timelimit = be->be_timelimit;
-       *sizelimit = be->be_sizelimit;
+       *limit = &be->be_def_limit;
 
        /*
         * anonymous or no regex-based limits? 
@@ -44,16 +41,14 @@ get_limits(
                switch ( lm[0]->lm_type) {
                case SLAP_LIMITS_EXACT:
                        if ( strcmp( lm[0]->lm_dn_pat, ndn ) == 0 ) {
-                               *timelimit = lm[0]->lm_timelimit;
-                               *sizelimit = lm[0]->lm_sizelimit;
+                               *limit = &lm[0]->lm_limits;
                                return( 0 );
                        }
                        break;
 
                case SLAP_LIMITS_REGEX:
                        if ( regexec( &lm[0]->lm_dn_regex, ndn, 0, NULL, 0) == 0 ) {
-                               *timelimit = lm[0]->lm_timelimit;
-                               *sizelimit = lm[0]->lm_sizelimit;
+                               *limit = &lm[0]->lm_limits;
                                return( 0 );
                        }
                        break;
@@ -69,18 +64,18 @@ get_limits(
 
 int
 add_limits(
-       Backend         *be,
-       int             type,
-       const char      *pattern,
-       int             timelimit,
-       int             sizelimit
+       Backend                 *be,
+       int                     type,
+       const char              *pattern,
+       struct slap_limits_set  *limit
 )
 {
        int                     i;
        struct slap_limits      *lm;
        
        assert( be );
-       assert( pattern);
+       assert( pattern );
+       assert( limit );
 
        lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );
 
@@ -107,8 +102,7 @@ add_limits(
                break;
        }
 
-       lm->lm_timelimit = timelimit;
-       lm->lm_sizelimit = sizelimit;
+       lm->lm_limits = *limit;
 
        i = 0;
        if ( be->be_limits != NULL ) {
@@ -134,8 +128,7 @@ parse_limits(
 {
        int     type = SLAP_LIMITS_UNDEFINED;
        char    *pattern;
-       int     timelimit;
-       int     sizelimit;
+       struct slap_limits_set limit;
        int     i;
 
        assert( be );
@@ -155,13 +148,12 @@ parse_limits(
                return( -1 );
        }
 
-       timelimit = be->be_timelimit;
-       sizelimit = be->be_sizelimit;
+       limit = be->be_def_limit;
 
        /*
         * syntax:
         *
-        * "limits" <pattern> <limit> [ <limit> [ ... ] ]
+        * "limits" <pattern> <limit> [ ... ]
         * 
         * 
         * <pattern>:
@@ -171,7 +163,9 @@ parse_limits(
         * 
         * <limit>:
         *
-        * { "time" | "size" } "=" <value>
+        * "time" [ "." { "soft" | "hard" } ] "=" <integer>
+        *
+        * "size" [ "." { "soft" | "hard" | "unchecked" } ] "=" <integer>
         */
        
        pattern = argv[1];
@@ -210,27 +204,122 @@ parse_limits(
        }
 
        for ( i = 2; i < argc; i++ ) {
-               if ( strncasecmp( argv[i], "time=", 5) == 0 ) {
-                       timelimit = atoi( argv[i]+5 );
-               } else if ( strncasecmp( argv[i], "size=", 5) == 0 ) {
-                       sizelimit = atoi( argv[i]+5 );
-               } else {
+               if ( parse_limit( argv[i], &limit ) ) {
+
 #ifdef NEW_LOGGING
                        LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
                                "%s : line %d: unknown limit type \"%s\" in "
-                               "\"limits <pattern> <limits>\" line "
-                               "(ignored).\n",
+                               "\"limits <pattern> <limits>\" line.\n",
                        fname, lineno, argv[i] ));
 #else
                        Debug( LDAP_DEBUG_ANY,
                                "%s : line %d: unknown limit type \"%s\" in "
-                               "\"limits <pattern> <limits>\" line "
-                               "(ignored).\n",
+                               "\"limits <pattern> <limits>\" line.\n",
                        fname, lineno, argv[i] );
 #endif
+
+                       return( 1 );
                }
        }
+
+       /*
+        * sanity checks ...
+        */
+       if ( limit.lms_t_hard > 0 && limit.lms_t_hard < limit.lms_t_soft ) {
+               limit.lms_t_hard = limit.lms_t_soft;
+       }
+       
+       if ( limit.lms_s_hard > 0 && limit.lms_s_hard < limit.lms_s_soft ) {
+               limit.lms_s_hard = limit.lms_s_soft;
+       }
        
-       return( add_limits( be, type, pattern, timelimit, sizelimit ) );
+       return( add_limits( be, type, pattern, &limit ) );
+}
+
+int
+parse_limit(
+       const char              *arg,
+       struct slap_limits_set  *limit
+)
+{
+       assert( arg );
+       assert( limit );
+
+       if ( strncasecmp( arg, "time", 4 ) == 0 ) {
+               arg += 4;
+
+               if ( arg[0] == '.' ) {
+                       arg++;
+                       if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
+                               arg += 4;
+                               if ( arg[0] != '=' ) {
+                                       return( 1 );
+                               }
+                               arg++;
+                               limit->lms_t_soft = atoi( arg );
+                               
+                       } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
+                               arg += 4;
+                               if ( arg[0] != '=' ) {
+                                       return( 1 );
+                               }
+                               arg++;
+                               limit->lms_t_hard = atoi( arg );
+                               
+                       } else {
+                               return( 1 );
+                       }
+                       
+               } else if ( arg[0] == '=' ) {
+                       limit->lms_t_soft = atoi( arg );
+                       limit->lms_t_hard = 0;
+                       
+               } else {
+                       return( 1 );
+               }
+
+       } else if ( strncasecmp( arg, "size", 4 ) == 0 ) {
+               arg += 4;
+               
+               if ( arg[0] == '.' ) {
+                       arg++;
+                       if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
+                               arg += 4;
+                               if ( arg[0] != '=' ) {
+                                       return( 1 );
+                               }
+                               arg++;
+                               limit->lms_s_soft = atoi( arg );
+                               
+                       } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
+                               arg += 4;
+                               if ( arg[0] != '=' ) {
+                                       return( 1 );
+                               }
+                               arg++;
+                               limit->lms_s_hard = atoi( arg );
+                               
+                       } else if ( strncasecmp( arg, "unchecked", 9 ) == 0 ) {
+                               arg += 9;
+                               if ( arg[0] != '=' ) {
+                                       return( 1 );
+                               }
+                               arg++;
+                               limit->lms_s_unchecked = atoi( arg );
+                               
+                       } else {
+                               return( 1 );
+                       }
+                       
+               } else if ( arg[0] == '=' ) {
+                       limit->lms_s_soft = atoi( arg );
+                       limit->lms_s_hard = 0;
+                       
+               } else {
+                       return( 1 );
+               }
+       }
+
+       return 0;
 }
 
index 88af06bf2c2ccc947319ef538d9adaa43ea87aaf..e8bf36c2f8fd6a339ca12f6c5e7e6f80162dfc66 100644 (file)
@@ -400,12 +400,14 @@ LDAP_SLAPD_F (int) test_filter LDAP_P((
  * limits.c
  */
 LDAP_SLAPD_F (int) get_limits LDAP_P((
-       Backend *be, const char *ndn, int *timelimit, int *sizelimit ));
+       Backend *be, const char *ndn, struct slap_limits_set **limit ));
 LDAP_SLAPD_F (int) add_limits LDAP_P((
        Backend *be, int type, const char *pattern, 
-       int timelimit, int sizelimit ));
+       struct slap_limits_set *limit ));
 LDAP_SLAPD_F (int) parse_limits LDAP_P((
         Backend *be, const char *fname, int lineno, int argc, char **argv ));
+LDAP_SLAPD_F (int) parse_limit LDAP_P(( const char *arg, 
+       struct slap_limits_set *limit ));
 
 /*
  * lock.c
@@ -830,8 +832,7 @@ LDAP_SLAPD_F (slap_ssf_set_t)       global_ssf_set;
 LDAP_SLAPD_F (struct berval **)        default_referral;
 LDAP_SLAPD_F (char *)          replogfile;
 LDAP_SLAPD_F (const char)      Versionstr[];
-LDAP_SLAPD_F (int)             defsize;
-LDAP_SLAPD_F (int)             deftime;
+LDAP_SLAPD_F (struct slap_limits_set)          deflimit;
 LDAP_SLAPD_F (int)             g_argc;
 LDAP_SLAPD_F (slap_access_t)   global_default_access;
 LDAP_SLAPD_F (int)             global_lastmod;
index 0dcecd3fa4990449d7aef01710aa5e8dfd67d097..aaefe20868799398c619daabda0641c32ad03128 100644 (file)
@@ -814,6 +814,17 @@ struct slap_replica_info {
        char  **ri_nsuffix;     /* array of suffixes this replica accepts */
 };
 
+struct slap_limits_set {
+       /* time limits */
+       int     lms_t_soft;
+       int     lms_t_hard;
+
+       /* size limits */
+       int     lms_s_soft;
+       int     lms_s_hard;
+       int     lms_s_unchecked;
+};
+
 struct slap_limits {
        int     lm_type;        /* type of pattern */
 #define SLAP_LIMITS_UNDEFINED  0x0000
@@ -821,8 +832,7 @@ struct slap_limits {
 #define SLAP_LIMITS_REGEX      0x0002
        regex_t lm_dn_regex;    /* regex-based size and time limits */
        char   *lm_dn_pat;      /* ndn for EXACT; pattern for REGEX */
-       int     lm_timelimit;
-       int     lm_sizelimit;
+       struct slap_limits_set  lm_limits;
 };
 
 /* temporary aliases */
@@ -920,8 +930,9 @@ struct slap_backend_db {
        char    *be_root_ndn;   /* the magic "root" normalized dn for this db   */
        struct berval be_root_pw;       /* the magic "root" password for this db        */
        unsigned int be_max_deref_depth;       /* limit for depth of an alias deref  */
-       int     be_sizelimit;   /* size limit for this backend             */
-       int     be_timelimit;   /* time limit for this backend             */
+#define be_sizelimit   be_def_limit.lms_s_soft
+#define be_timelimit   be_def_limit.lms_t_soft
+       struct slap_limits_set be_def_limit; /* default limits */
        struct slap_limits **be_limits; /* regex-based size and time limits */
        AccessControl *be_acl;  /* access control list for this backend    */
        slap_access_t   be_dfltaccess;  /* access given if no acl matches          */
index f8ce0e07ab07c9f96d8a5a6bc511fce80bcd4c6a..fb3a1f24c303981dd86759bf1655cc4e23faf886 100644 (file)
@@ -209,7 +209,12 @@ int parse_limits( Backend *be, const char *fname, int lineno, int argc, char **a
        return 0;
 }
 
-int get_limits( Backend *be, const char *ndn, int *timelimit, int *sizelimit )
+int parse_limit( const char *arg, struct slap_limits_set *limit )
+{
+       return 0;
+}
+
+int get_limits( Backend *be, const char *ndn, struct slap_limits_set **limit )
 {
        return 0;
 }